Kit Wai Chan - Fotolia
- It loads and initializes the Blazor application in the browser.
- It provides direct DOM manipulation, allowing Blazor to perform UI updates.
It's possible that in the future this file will no longer be required, but this depends on how fast features are added to WebAssembly and adopted by browsers. For now, it's an essential part of the framework.
Now we've cleared that up, let's get back to our booting Blazor app. I want to point out that the files returned from the server are all static files. They haven't required any server-side compilation or manipulation. This means that they can be hosted on any service that offers static hosting because there's no requirement for a .NET runtime to be present on the server. For the first time, this opens up free hosting options such as GitHub pages to .NET developers (applies to standalone Blazor WebAssembly applications only).
Once the browser has received all the initial files from the web server, it can process them and construct the DOM. Next, blazor.webassembly.js is executed; this performs many actions, but in the context of starting a Blazor WebAssembly app, it downloads a file called blazor.boot.json, which contains an inventory of all of the framework and application files that are required to run the app.
Most of these files are normal .NET assemblies; there's nothing special about them and they could be run on any compatible .NET runtime. Another type of file is downloaded called dotnet.wasm.
The dotnet.wasm file is a complete .NET runtime -- the mono .NET runtime to be exact -- which has been compiled to WebAssembly.
At this point in time, only the .NET runtime is compiled to WebAssembly; the framework and application are standard .NET assemblies. In the future, a feature called AOT (Ahead of Time) compiling will be introduced, which allows developers to compile parts of their applications into WebAssembly. The benefit of this is performance: Any code compiled to WebAssembly is many times more performant than the interpreted approach used today. This comes with a tradeoff, which is size. AOT compiled code is bigger than the standard assemblies, meaning a larger overall download size for the application.
Once the blazor.boot.json file has been downloaded and the files listed in it have been downloaded, it's time for the application to be run. The WebAssembly .NET runtime is initialized, which in turn loads the Blazor framework and finally the application itself. At this point we have a running Blazor application that exists entirely inside the client's browser. Aside from requesting additional data (if applicable), there's no further reliance on the server.
Calculating UI updates
We now understand how a Blazor WebAssembly application boots up, but how do UI updates get calculated? As we did for the initialization process, we're going to follow a scenario to understand how this happens and what Blazor does (Figure 2).
For our scenario, we have a Blazor WebAssembly application with two pages, Home and Counter. Neither of these pages have anything on them except a heading saying either Home or Counter, respectively. The user is on the home page of the application and will click on a link to go to the counter page. We'll follow the process Blazor goes through to update the UI from that of the home page to the counter page.
The router checks its routing table for any routable components that match the link the user has attempted to navigate to. In our case, it finds a match with the Counter component, and a new instance of that component is created and the relevant lifecycle methods are executed.
All of this has happened client-side in the user browser. There was no need for a server during any point in this process. It's fair to say that in a real-world application, you would probably make a call out to a server at some point in this process. This usually happens during the execution of the lifecycle methods of the component being navigated to in order to load some initial data for the component, but this depends on the individual application.
Benefits and tradeoffs
Now that we know a bit more about how the Blazor WebAssembly hosting model works, let talk about the benefits and tradeoffs of choosing this model. Let's start with the benefits.
- Applications run on the client. This means there's much less load on the server; you can offload much of the work to the client. This could lead to significant cost savings on server infrastructure and improve the scalability of an application.
- Apps can work in offline scenarios. As the app runs entirely inside the browser, there's no need for a persistent connection to the server, making applications more tolerant to unstable network connections. It's also trivial to enable progressive web application In fact, Blazor WebAssembly has this as an option you can select when creating your application.
- Apps are deployed as static files. As Blazor WebAssembly apps are static files, they can be deployed anywhere static hosting is available. This opens up some options that have never been available to .NET developers historically. Services such as GitHub pages, Netlify, Azure Blob Storage, AWS S3 Buckets and Azure Static Web Sites are all options for hosting standalone Blazor WebAssembly applications.
- Code sharing. Potentially one of the greatest benefits with Blazor WebAssembly isusing C# on the server. You can now use the same C# objects on your client as you use on the server. The days of keeping TypeScript models in sync with their C# equivalent and vice versa, are over.
Nothing is a silver bullet. Let's understand some tradeoffs of this model.
- Payload. The initial download size for a Blazor WebAssembly app can be considered large. The project template weighs in at around 1.8 MB when published. This is largely due to the fact Blazor needs to ship an entire .NET runtime to the client, which comes in at around 600 KB. This is a one-time cost, as the runtime and many of the framework assemblies are cached on the first load, which means subsequent loads can be a small as a few kilobytes.
- Load time. A knock-on effect of the payload size can be load time. If the user is on a poor internet connection, the amount of time required to download the initial files is higher, which delays the start of the application, leaving the user with a loading message of some kind. This can be offset slightly using server-side prerendering, and although this gives the user something more interesting to look at initially, the app still won't be interactive until all files have been downloaded and initialized. Server-side prerendering for Blazor WebAssembly apps also requires an NET Core element on the server, which negates any free hosting options.