Skip to content

Commit

Permalink
feat(templates): add Blazor WASM Standalone samples to cd pipelines a…
Browse files Browse the repository at this point in the history
…nd a bunch of unrelated stuff #9506 (#9507)
  • Loading branch information
ysmoradi authored Dec 17, 2024
1 parent 2d1d6bd commit 45b0edd
Show file tree
Hide file tree
Showing 14 changed files with 188 additions and 191 deletions.
50 changes: 50 additions & 0 deletions .github/workflows/admin-sample.cd.yml
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,56 @@ jobs:
path: ${{env.DOTNET_ROOT}}/server
include-hidden-files: true # Required for wwwroot/.well-known folder

deploy_blazor_wasm_standalone:
name: build blazor wasm standalone
runs-on: ubuntu-24.04

steps:

- name: Checkout source code
uses: actions/checkout@v4

- name: Setup .NET
uses: actions/setup-dotnet@v4
with:
global-json-file: src/global.json

- name: Create project from Boilerplate
run: |
cd src/Templates/Boilerplate && dotnet build -c Release
dotnet pack -c Release -o . -p:ReleaseVersion=0.0.0 -p:PackageVersion=0.0.0
dotnet new install Bit.Boilerplate.0.0.0.nupkg
cd ../../../ && dotnet new bit-bp --name AdminPanel --database PostgreSQL --sample Admin --appInsights --sentry --serverUrl ${{ env.SERVER_ADDRESS }} --filesStorage AzureBlobStorage --notification --captcha reCaptcha --signalR --framework net9.0
- name: Update core appsettings.json
uses: devops-actions/variable-substitution@v1.2
with:
files: 'AdminPanel/src/Shared/appsettings.json, AdminPanel/src/Client/AdminPanel.Client.Core/appsettings.json, AdminPanel/src/Client/AdminPanel.Client.Web/appsettings.json, AdminPanel/src/Client/AdminPanel.Client.Web/appsettings.Production.json'
env:
ServerAddress: ${{ env.SERVER_ADDRESS }}
Logging.Sentry.Dsn: ${{ secrets.ADMINPANEL_SENTRY_DSN }}
GoogleRecaptchaSiteKey: ${{ secrets.GOOGLE_RECAPTCHA_SITE_KEY }}
AdsPushVapid.PublicKey: ${{ secrets.ADMINPANEL_PUBLIC_VAPIDKEY }}
ApplicationInsights.ConnectionString: ${{ secrets.APPLICATION_INSIGHTS_CONNECTION_STRING }}

- uses: actions/setup-node@v4
with:
node-version: 22

- name: Install wasm
run: cd src && dotnet workload install wasm-tools

- name: Generate CSS/JS files
run: dotnet build AdminPanel/src/Client/AdminPanel.Client.Core/AdminPanel.Client.Core.csproj -t:BeforeBuildTasks -p:Version="${{ vars.APPLICATION_DISPLAY_VERSION}}" --no-restore -c Release

- name: Publish
run: dotnet publish AdminPanel/src/Client/AdminPanel.Client.Web/AdminPanel.Client.Web.csproj -c Release -p:PwaEnabled=true -o ${{env.DOTNET_ROOT}}/client -p:Version="${{ vars.APPLICATION_DISPLAY_VERSION}}"

- name: Upload to asw
run: |
npm install -g @azure/static-web-apps-cli
swa deploy --deployment-token ${{ secrets.ADMINPANEL_ASW_TOKEN }} --env production --app-location ${{env.DOTNET_ROOT}}/client/wwwroot
deploy_api_blazor:
name: deploy api + blazor
needs: build_api_blazor
Expand Down
47 changes: 47 additions & 0 deletions .github/workflows/todo-sample.cd.yml
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,53 @@ jobs:
CLOUDFLARE_ZONE: ${{ secrets.BITPLATFORM_DEV_CLOUDFLARE_ZONE }}
CLOUDFLARE_TOKEN: ${{ secrets.CLOUDFLARE_TOKEN }}

deploy_blazor_wasm_standalone:
name: build blazor wasm standalone
runs-on: ubuntu-24.04

steps:

- name: Checkout source code
uses: actions/checkout@v4

- name: Setup .NET
uses: actions/setup-dotnet@v4
with:
global-json-file: src/global.json

- name: Create project from Boilerplate
run: |
cd src/Templates/Boilerplate && dotnet build -c Release
dotnet pack -c Release -o . -p:ReleaseVersion=0.0.0 -p:PackageVersion=0.0.0
dotnet new install Bit.Boilerplate.0.0.0.nupkg
cd ../../../ && dotnet new bit-bp --name TodoSample --database PostgreSQL --sample Todo --serverUrl ${{ env.SERVER_ADDRESS }} --filesStorage AzureBlobStorage --notification --captcha reCaptcha --framework net9.0
- name: Update core appsettings.json
uses: devops-actions/variable-substitution@v1.2
with:
files: 'TodoSample/src/Shared/appsettings.json, TodoSample/src/Client/TodoSample.Client.Core/appsettings.json, TodoSample/src/Client/TodoSample.Client.Web/appsettings.json, TodoSample/src/Client/TodoSample.Client.Web/appsettings.Production.json'
env:
ServerAddress: ${{ env.SERVER_ADDRESS }}
GoogleRecaptchaSiteKey: ${{ secrets.GOOGLE_RECAPTCHA_SITE_KEY }}

- uses: actions/setup-node@v4
with:
node-version: 22

- name: Install wasm
run: cd src && dotnet workload install wasm-tools

- name: Generate CSS/JS files
run: dotnet build TodoSample/src/Client/TodoSample.Client.Core/TodoSample.Client.Core.csproj -t:BeforeBuildTasks -p:Version="${{ vars.APPLICATION_DISPLAY_VERSION}}" --no-restore -c Release

- name: Publish
run: dotnet publish TodoSample/src/Client/TodoSample.Client.Web/TodoSample.Client.Web.csproj -c Release -p:PwaEnabled=true -o ${{env.DOTNET_ROOT}}/client -p:Version="${{ vars.APPLICATION_DISPLAY_VERSION}}" -p:RunAOTCompilation=true -p:MultilingualEnabled=false

- name: Upload to asw
run: |
npm install -g @azure/static-web-apps-cli
swa deploy --deployment-token ${{ secrets.TODO_ASW_TOKEN }} --env production --app-location ${{env.DOTNET_ROOT}}/client/wwwroot
build_blazor_hybrid_windows:
name: build blazor hybrid (windows)
runs-on: windows-2022
Expand Down
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,9 @@ The following apps are our open-source projects powered by the bit platform show
1. [bitplatform.dev](https://bitplatform.dev): .NET 9 Pre-rendered SPA with Blazor WebAssembly
2. [blazorui.bitplatform.dev](https://blazorui.bitplatform.dev): .NET 9 Pre-rendered PWA with Blazor WebAssembly
3. [todo.bitplatform.dev](https://todo.bitplatform.dev): .NET 8 Pre-rendered PWA with Blazor WebAssembly
5. [adminpanel.bitplatform.dev](https://adminpanel.bitplatform.dev): .NET 9 PWA with Blazor WebAssembly Standalone (Hosted on Cloudflare Pages)
5. [adminpanel.bitplatform.dev](https://adminpanel.bitplatform.dev): .NET 9 PWA with Blazor WebAssembly
6. [adminpanel.bitplatform.cc](https://adminpanel.bitplatform.cc): .NET 9 PWA with Blazor WebAssembly Standalone (Free Azure static web app)
7. [todo.bitplatform.cc](https://todo.bitplatform.cc): AOT Compiled .NET 9 PWA with Blazor WebAssembly Standalone (Free Azure static web app)

[Todo](https://todo.bitplatform.dev) & [Adminpanel](https://adminpanel.bitplatform.dev) web apps will launch their respective Android and iOS applications if you have already installed them, mirroring the behavior of apps like YouTube and Instagram.

Expand Down
47 changes: 22 additions & 25 deletions src/BlazorUI/Demo/Bit.BlazorUI.Demo.Server/Components/App.razor
Original file line number Diff line number Diff line change
Expand Up @@ -60,34 +60,31 @@
}
<Routes @rendermode=renderMode />

@if (HttpContext.Request.IsCrawlerClient() is false)
<Script src="_framework/blazor.web.js?v=9.0.0" autostart="false"></Script>
@if (AppRenderMode.PwaEnabled)
{
<Script src="_content/Bit.Bswup/bit-bswup.js"></Script>
<Script src="_content/Bit.Bswup/bit-bswup.progress.js"></Script>
<AppBswupProgressBar />
}
else
{
<Script src="_framework/blazor.web.js?v=9.0.0" autostart="false"></Script>
@if (AppRenderMode.PwaEnabled)
{
<Script src="_content/Bit.Bswup/bit-bswup.js"></Script>
<Script src="_content/Bit.Bswup/bit-bswup.progress.js"></Script>
<AppBswupProgressBar />
}
else
{
<Script>
Blazor.start({
webAssembly: {
loadBootResource: function (type, name, defaultUri, integrity) {
if (integrity != null && integrity != '')
return `${defaultUri}?v=${integrity}`;
return null; // default blazor asset loading mechanism.
}
<Script>
Blazor.start({
webAssembly: {
loadBootResource: function (type, name, defaultUri, integrity) {
if (integrity != null && integrity != '')
return `${defaultUri}?v=${integrity}`;
return null; // default blazor asset loading mechanism.
}
});
</Script>
}
<Script src="_content/Bit.BlazorUI.Demo.Client.Core/prism-1.28.0/prism.js"></Script>
<Script src="_content/Bit.BlazorUI/scripts/bit.blazorui.js"></Script>
<Script src="_content/Bit.BlazorUI.Extras/scripts/bit.blazorui.extras.js"></Script>
<Script src="_content/Bit.BlazorUI.Demo.Client.Core/scripts/app.js"></Script>
}
});
</Script>
}
<Script src="_content/Bit.BlazorUI.Demo.Client.Core/prism-1.28.0/prism.js"></Script>
<Script src="_content/Bit.BlazorUI/scripts/bit.blazorui.js"></Script>
<Script src="_content/Bit.BlazorUI.Extras/scripts/bit.blazorui.extras.js"></Script>
<Script src="_content/Bit.BlazorUI.Demo.Client.Core/scripts/app.js"></Script>
</body>

</html>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,23 +18,4 @@ public static Uri GetBaseUrl(this HttpRequest req)

return uriBuilder.Uri;
}

public static bool IsCrawlerClient(this HttpRequest request)
{
if (request.Headers.TryGetValue(HeaderNames.UserAgent, out StringValues userAgentHeaderValue) is false)
return false;

string? userAgent = userAgentHeaderValue.FirstOrDefault();

if (userAgent is null)
return false;

if (userAgent.Contains("google", StringComparison.InvariantCultureIgnoreCase)) return true;

if (userAgent.Contains("bing", StringComparison.InvariantCultureIgnoreCase)) return true;

if (userAgent.Contains("lighthouse", StringComparison.InvariantCultureIgnoreCase)) return true;

return false;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,7 @@ self.assetsExclude = [
/bit\.blazorui\.fluent-light\.css$/,
// If a PDF viewer is needed in the PWA, remove these two lines:
/pdfjs-4\.7\.76\.js$/,
/pdfjs-4\.7\.76-worker\.js$/,
/Boilerplate\.Client\.Web\.styles\.css$/
/pdfjs-4\.7\.76-worker\.js$/
];
self.externalAssets = [
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -124,10 +124,15 @@ public static void AddServerApiProjectServices(this WebApplicationBuilder builde
configuration.Bind(settings);

var webClientUrl = settings.WebClientUrl;
var allowedOrigins = settings.Cors?.AllowedOrigins?.ToList() ?? [];

policy.SetIsOriginAllowed(origin =>
AllowedOriginsRegex().IsMatch(origin) ||
(string.IsNullOrEmpty(webClientUrl) is false && string.Equals(origin, webClientUrl, StringComparison.InvariantCultureIgnoreCase)))
if (string.IsNullOrEmpty(webClientUrl) is false)
{
allowedOrigins.Add(webClientUrl);
}

policy.SetIsOriginAllowed(origin => AllowedOriginsRegex().IsMatch(origin)
|| allowedOrigins.Any(o => string.Equals(o, origin, StringComparison.InvariantCultureIgnoreCase)))
.AllowAnyHeader()
.AllowAnyMethod()
.WithExposedHeaders(HeaderNames.RequestId);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ public partial class ServerApiSettings : SharedSettings

public ForwardedHeadersOptions? ForwardedHeaders { get; set; }

public CorsOptions? Cors { get; set; }

public override IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
{
var validationResults = base.Validate(validationContext).ToList();
Expand Down Expand Up @@ -157,3 +159,8 @@ public partial class SmsOptions
string.IsNullOrEmpty(TwilioAccountSid) is false &&
string.IsNullOrEmpty(TwilioAutoToken) is false;
}

public class CorsOptions
{
public string[] AllowedOrigins { get; set; } = [];
}
Original file line number Diff line number Diff line change
Expand Up @@ -68,49 +68,46 @@

<Routes @rendermode=renderMode />

@if (HttpContext.Request.IsCrawlerClient() is false)
{
@*#if (framework == "net9.0")*@
<Script src="_framework/blazor.web.js?ver=9.0.0" autostart="false"></Script>
@*#else*@
@*#if (IsInsideProjectTemplate == true)*@
/*
@*#endif)*@
<Script src="_framework/blazor.web.js?ver=8.0.11" autostart="false"></Script>
@*#if (IsInsideProjectTemplate == true)*@
*/
@*#endif)*@
@*#if (framework == "net9.0")*@
<Script src="_framework/blazor.web.js?ver=9.0.0" autostart="false"></Script>
@*#else*@
@*#if (IsInsideProjectTemplate == true)*@
/*
@*#endif)*@
<!-- Ensure that the version of `blazor.web.js` matches the version specified in `service-worker.published.js`.
This alignment is necessary for the PWA functionality of the Blazor app to work correctly. -->
@if (serverWebSettings.WebAppRender.PwaEnabled)
{
<Script src="_content/Bit.Bswup/bit-bswup.js"></Script>
<Script src="_content/Bit.Bswup/bit-bswup.progress.js"></Script>
<AppBswupProgressBar />
}
else
{
<Script>
Blazor.start({
webAssembly: {
loadBootResource: function (type, name, defaultUri, integrity) {
if (integrity != null && integrity != '')
return `${defaultUri}?v=${integrity}`;
return null; // default blazor asset loading mechanism.
}
<Script src="_framework/blazor.web.js?ver=8.0.11" autostart="false"></Script>
@*#if (IsInsideProjectTemplate == true)*@
*/
@*#endif)*@
@*#endif)*@
<!-- Ensure that the version of `blazor.web.js` matches the version specified in `service-worker.published.js`.
This alignment is necessary for the PWA functionality of the Blazor app to work correctly. -->
@if (serverWebSettings.WebAppRender.PwaEnabled)
{
<Script src="_content/Bit.Bswup/bit-bswup.js"></Script>
<Script src="_content/Bit.Bswup/bit-bswup.progress.js"></Script>
<AppBswupProgressBar />
}
else
{
<Script>
Blazor.start({
webAssembly: {
loadBootResource: function (type, name, defaultUri, integrity) {
if (integrity != null && integrity != '')
return `${defaultUri}?v=${integrity}`;
return null; // default blazor asset loading mechanism.
}
});
</Script>
}
<Script src="_content/Bit.Butil/bit-butil.js"></Script>
@*#if (offlineDb == true)*@
<Script src="_content/Bit.Besql/bit-besql.js"></Script>
@*#endif*@
<Script src="_content/Bit.BlazorUI/scripts/bit.blazorui.js"></Script>
<Script src="_content/Boilerplate.Client.Core/scripts/app.js"></Script>
<Script src="_content/Bit.BlazorUI.Extras/scripts/bit.blazorui.extras.js"></Script>
}
});
</Script>
}
<Script src="_content/Bit.Butil/bit-butil.js"></Script>
@*#if (offlineDb == true)*@
<Script src="_content/Bit.Besql/bit-besql.js"></Script>
@*#endif*@
<Script src="_content/Bit.BlazorUI/scripts/bit.blazorui.js"></Script>
<Script src="_content/Boilerplate.Client.Core/scripts/app.js"></Script>
<Script src="_content/Bit.BlazorUI.Extras/scripts/bit.blazorui.extras.js"></Script>
</body>

</html>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,23 +18,4 @@ internal static Uri GetBaseUrl(this HttpRequest req)

return uriBuilder.Uri;
}

public static bool IsCrawlerClient(this HttpRequest request)
{
if (request.Headers.TryGetValue(HeaderNames.UserAgent, out StringValues userAgentHeaderValue) is false)
return false;

string? userAgent = userAgentHeaderValue.FirstOrDefault();

if (userAgent is null)
return false;

if (userAgent.Contains("google", StringComparison.InvariantCultureIgnoreCase)) return true;

if (userAgent.Contains("bing", StringComparison.InvariantCultureIgnoreCase)) return true;

if (userAgent.Contains("lighthouse", StringComparison.InvariantCultureIgnoreCase)) return true;

return false;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,26 +17,4 @@ public static string GetBaseUrl(this HttpRequest req)

return uriBuilder.Uri.AbsoluteUri;
}

public static bool IsCrawlerClient(this HttpRequest request)
{
var agent = GetLoweredUserAgent(request);

if (agent.Contains("google")) return true;

if (agent.Contains("bing")) return true;

if (agent.Contains("lighthouse")) return true;

return false;
}

private static string GetLoweredUserAgent(HttpRequest request)
{
var userAgent = request.Headers[HeaderNames.UserAgent].ToString();

if (string.IsNullOrEmpty(userAgent)) return string.Empty;

return userAgent.ToLowerInvariant();
}
}
Loading

0 comments on commit 45b0edd

Please sign in to comment.