This slide explains how to prerendering a Blazor WebAssembly app hosted on the static web hosting and save them to static HTML files at publishing time.
Report
Share
Report
Share
1 of 29
Download to read offline
More Related Content
Pre-render Blazor WebAssembly on static web hosting at publishing time
1. 1
- Behind the scenes of "Awesome Blazor Browser" -
Pre-render
Blazor WebAssembly
on static web hosting at publishing time
3. 3
3
"Awesome Blazor Browser"
A dedicated web app for browsing the README of the
"Awesome Blazor" GitHub repository.
▪ It's a Blazor WebAssembly app (SPA).
▪ It's hosted on GitHub Pages.
▪ It's deployed by GitHub Actions.
▪ It provides us with easy navigation and
searching for the "Awesome Blazor"
collection.
• It fetches the README text from the
"Awesome Blazor" GitHub repository, parses,
restructures it, and shows the collection in a
searchable UI.
https://j.mp/awesome-blazor-browser 3
4. 4
The "Awesome Blazor Browser" had a problem…
The Internet search result of the "Awesome Blazor Browser" was really bad.
- Currently, Google crawlers can index of a content that Blazor Wasm apps rendered.
- The server-side prerendering strategy is also effective when the app is hosted on an ASP.NET Core server.
See also: https://andrewlock.net/enabling-prerendering-for-blazor-webassembly-apps/
5. 5
5
"Pre-rendering" at publishing time can resolve it.
• It's something like "Static Site Generation (SSG)".
• Make the published "index.html" to contains the same
content that the app renders into the browser after launching
the app.
• Additionally, if the app has some route URL, each URL should
be rendered and be saved into a corresponding static HTML.
• In this case, we have to do this in a GitHub Actions script
that publishes the site.
7. 7
7
Create your own pre-render C# program
• Add an ASP.NET Core server project
for hosting the Blazor WebAssembly.
• And configure it to server-side render
with "static" render mode.
• Add an app that boots the host and
fetches contents from the host by
HttpClient and saves them to static
HTML files.
For more detail, see also "andrewlock.net".
Use the "react-snap"
• "react-snap" is a NodeJS tool.
• It traverses the published SPA contents
using a headless Chromium browser
and saves them to static HTML files.
• The Blazor WebAssembly side is not
required any code changes.
For more detail, see also "swimburger.net".
I could find some solutions on the Internet.
8. 8
8
…But I could not be satisfied with those solutions.
Create your own pre-render C# program
• We have to write massive and
complicated C# codes.
• Those C# codes depend on individual
Blazor WebAssembly project strongly.
• That means the programs of this
approach can't reuse out-of-the-box for
the other Blazor WebAssembly project.
Use the "react-snap"
• It can't wait for an "OnInitializedAsync"
async method to be completed.
• Therefore, in some cases, it saved an
intermediate content result.
• It saves client-side process rendered
HTML, so the results are a bit different
from server-side rendered HTML.
• So, we must rewrite pre-rendered HTML
files after "react-snap" does.
9. 9
9
…So, I started yet another project to
resolve it.
"Reinvent a wheel? Yes, I know."
10. 10
10
My approach
and goal are:
Based on standard server-side
prerendering that is hosted on
an ASP.NET Core server.
Make the code changes of the
Blazor WebAssembly side to be
minimum.
Make it as a NuGet package.
11. 11
11
…and finally, I did it !
"BlazorWasmPreRendering.Build"
https://www.nuget.org/packages/BlazorWasmPreRendering.Build/
12. 12
12
Only you need to do is just adding that package!
> dotnet add package BlazorWasmPreRendering.Build --version 1.0.0-preview.4.1
15. 15
15
Before After
In this case, I used the "Toolbelt.Blazor.HeadElement" NuGet package to change the document title.
See also: https://dev.to/j_sakamoto/yet-another-way-to-changing-the-page-title-in-blazor-and-more-43k
16. 16
You don't need to change the GitHub action script.
In this case, I used the "PublishSPAforGitHubPages.Build"
NuGet package to simplify publishing the Blazor
WebAssembly app to GitHub Pages.
See also: https://dev.to/j_sakamoto/the-easier-way-to-
publish-your-blazor-webassembly-app-for-github-pages-319l
This package also works on the
GitHub Action script to deploy to
Azure Static Web apps.
18. 18
18
"BlazorWasmPreRendering.Build" does…
• It starts its own ASP.NET Core web server instance.
• The server instance loads the published "index.html" file and
creates the SPA fallback Razor page on the fly from that
"index.html".
• The server instance also loads the Blazor components DLL files
from the publish folder and finds an "App" root component.
• It configures the SPA fallback Razor page to do server-side
rendering with "static" rendering mode.
• It sends HTTP requests to itself and saves the responses to
static HTML files in the publish folder.
20. 20
20
2nd. Crawling step
📦 "BlazorWasmPreRendering.Build" 📂 Publish Folder ("/")
📄 "Index.html"
🎛 Web Server
🕹 Crawler
HTTP Request GET "/"
Response
<h1>Home</h1>
...
<a href="counter">
Counter</a>
... Save
<h1>Home</h1>
...
<a href="counter">
Counter</a>
...
Render
Detect Link
Response
<h1>Counter</h1>
... Save
<h1>Counter</h1>
...
Render
HTTP Request GET "/counter"
📂 "/counter"
📄 "index.html"
href="counter"
21. 21
21
2nd. Crawling step
📦 "BlazorWasmPreRendering.Build" 📂 Publish Folder ("/")
📄 "Index.html"
🎛 WebHost
🕹 Crawler
HTTP Request GET "/"
Response
<h1>Home</h1>
...
<a href="counter">
Counter</a>
... Save
<h1>Home</h1>
...
<a href="counter">
Counter</a>
...
Render
Detect Link
Response
<h1>Counter</h1>
... Save
<h1>Counter</h1>
...
Render
HTTP Request GET "/counter"
📂 "/counter"
📄 "index.html"
href="counter"
These processes are executed just before the end of "dotnet publish".
22. 22
22
But of course, it is not perfect.
"No Silver Bullet" ― Frederick Phillips Brooks, Jr.
23. 23
23
public static async Task Main(string[] args)
{
var builder = WebAssemblyHostBuilder.CreateDefault(args);
builder.RootComponents.Add<App>("#app");
var services = builder.Services;
var baseAddress = builder.HostEnvironment.BaseAddress;
await builder.Build().RunAsync();
}
"BlazorWasmPreRendering.Build" can't invoke the
Main method of the Blazor Wasm app side.
• "BlazorWasmPreRendering.Build"
runs your Blazor app on its own
server process.
• When your app depends on
custom services in a DI container,
but the "Main" method never be
invoked in the server process, the
app will fail because any services
are not registered to the DI
container in the server process.
services.AddTransient(sp => new HttpClient {
BaseAddress = new Uri(baseAddress) });
services.AddSingleton<MyService>();
Never invoked! 😱
24. 24
24
public static async Task Main(string[] args)
{
var builder = WebAssemblyHostBuilder.CreateDefault(args);
builder.RootComponents.Add<App>("#app");
var services = builder.Services;
var baseAddress = builder.HostEnvironment.BaseAddress;
await builder.Build().RunAsync();
}
So, you have to extract service registrations to
a method named "ConfigureServices()".
• "BlazorWasmPreRendering.Build"
will invoke this Blazor Wasm app's
"ConfigureServices()" method
within its startup process.
private static void ConfigureServices(
IServiceProvider services, string baseAddress)
{
}
ConfigureServices(services, baseAddress);
services.AddTransient(sp => new HttpClient {
BaseAddress = new Uri(baseAddress) });
services.AddSingleton<MyService>();
Will be invoked! 👍
25. 25
25
And this is still an experimental project.
• There are few results of using the
"BlazorWasmPreRendering.Build" yet.
• I'm not sure currently that "BlazorWasmPreRendering.Build"
works well on complicated real-world applications or not.
• I am still interested in the "react-snap" approach if it can
avoid the problem that it can't wait for the async initialization
because developers may use this approach with an out-of-
the-box experience.
27. 27
27
I hope "BlazorWasmPreRendering.Build" will save
your time
• This package will improve the Internet
search results of your static hosting
Blazor Wasm app with only minimal or
no code changes.
• But this is still an experimental project.
• I welcome anybody who forks and
improve this project or implement
other approaches.
28. 28
28
Appendix
• "Yet another way to changing the page title in Blazor, and more." | DEV Community
https://dev.to/j_sakamoto/yet-another-way-to-changing-the-page-title-in-blazor-and-more-43k
• "The easier way to publish your Blazor WebAssembly app for GitHub Pages" | DEV Community
https://dev.to/j_sakamoto/the-easier-way-to-publish-your-blazor-webassembly-app-for-github-pages-319l