Blazor WebAssembly facilitates the development of SPAs (Single-page applications) that run in the browser using C# instead of JavaScript as the primary programming language.
Executing C# code in the browser is a rather neat trick, made possible via the revolutionary WebAssembly technology which is an open web standard. However, the default mechanism employed by Blazor to achieve this is not the most optimal for runtime performance. By default, when you publish your Blazor WebAssembly application, a WebAssembly-compiled version of .NET (Mono) is downloaded to the browser and is used to run your .NET libraries via IL (Intermediate Language) interpretation.
Although the default approach performs well in many scenarios, it can be relatively slow when performing intensive work or rendering complex user interfaces. Thankfully, there is a way to greatly improve the performance of complex Blazor WebAssembly applications using ahead-of-time (AOT) compilation.
This article will explain how to enable AOT compilation for your project as simply as possible and will also cover how to make the process configurable when implementing continuous deployment.
Some considerations
Before jumping into the AOT compilation configuration steps, I would like to briefly discuss some considerations you should make before deciding to enable AOT compilation for your project.
Application size
First of all, enabling AOT compilation will increase the overall size of your application, since the compiled WebAssembly code isn’t as compact as the .NET IL (Intermediate Language) instructions. You will find that your application will likely double in size after enabling AOT compilation. Naturally, this will result in a slower start-up experience for users. However, it shouldn’t be a huge concern for line-of-business applications, since the application files will be cached after the initial download.
Publish duration
Secondly, the AOT compilation process is intensive. This means that publish times will increase quite significantly. You can expect deploying your application to take 3-4 times longer. In cases where you deploy code to multiple environments, you will likely want to consider enabling AOT compilation only for the environments that particularly need it. For example, the QA (Quality Assurance) testing environment or the final production environment.
Performance
Lastly, AOT compilation can make a huge difference to the performance of your application. The performance benefits are likely to be most noticeable in areas of your application that render many components on a single page and for computationally intensive tasks that run on the front end. You’ll likely notice an even bigger difference on less powerful devices and your application should feel smoother across the board.
After reviewing the above considerations, if you’re convinced that enabling AOT compilation for your Blazor WebAssembly project is right for you, I invite you to proceed to the next section!
Enabling AOT compilation
Let’s enable AOT compilation for a Blazor WebAssembly project.
In the subsections that follow, I’m using Visual Studio and targeting the latest version of .NET which is 8.0Â at the time of writing.
Project configuration
You can enable AOT compilation for your Blazor WebAssembly project via the Visual Studio tooling.
Assuming that you have your Blazor solution opened in Visual Studio, right-click on the Client (WebAssembly) project and select the ‘Properties’ option from the context menu to open the Properties window shown in the screenshot below.
If you search the Project Properties using the text ‘aot’ you should find that two properties are returned as shown above.
You should select the ‘Ahead-of-time (AOT) compilation’ checkbox which will apply the option immediately.
Note that the ‘Publish native AOT’ option is a separate thing you could consider enabling for your .NET APIs. The ‘Ahead-of-time (AOT) compilation’ option is the one we need for the Blazor WebAssembly AOT compilation.
Enabling the ‘Ahead-of-time (AOT) compilation’ in the Project Properties will automatically add the following two PropertyGroup
sections to your Blazor WebAssembly project (.csproj) file.
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">     <RunAOTCompilation>True</RunAOTCompilation>   </PropertyGroup>   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">     <RunAOTCompilation>True</RunAOTCompilation>   </PropertyGroup>
Note that you can double-click on your Blazor WebAssembly project node in Visual Studio to open the .csproj file and edit it directly within Visual Studio.
I recommend that you remove the first property group so that the AOT compilation will only run for Release builds.
As indicated in the Project Properties help text, the AOT compilation will run when the project is published.
Publishing
At this stage, you can test out the AOT compilation locally by publishing your project via Visual Studio.
Publish via Visual Studio
To publish via Visual Studio, right-click on the main Blazor project and select the ‘Publish…’ option from the context menu to open the Publish window shown in the screenshot below.
Note that for an ASP.NET Core Hosted Blazor WebAssembly app, the ‘main Blazor project’ will be the back-end API project, otherwise, it is the front-end client project you will need to publish.
Select the ‘Folder’ option from the list of Targets and press the ‘Next’ button.
You can accept the default output Location and press the ‘Finish’ button.
After the publishing setup process has finished and you close the Publish dialog, you will be brought back to the Publish window in Visual Studio.
Press the ‘Publish’ button to publish your project to the “bin\Release\net8.0\publish” folder. This may take a while depending on the size and complexity of your application.
After publishing has been completed, you can navigate to the publish directory and launch your application to check that it works locally before deploying it elsewhere (e.g. to a web server).
Publish error
You may receive the following error when attempting to publish your application.
NETSDK1147 To build this project, the following workloads must be installed: wasm-tools
To install these workloads, run the following command: dotnet workload restore
To fix the error, you can run the following command via the integrated Visual Studio terminal (View –> Terminal).
dotnet workload install wasm-tools
Note that you may receive a UAC (User Account Control) prompt which you will need to acknowledge.
Restart Visual Studio after the installation process has been completed.
If you try publishing the project again, you should find that the publishing finishes successfully.
Continuous deployment
If you use a platform such as Azure DevOps to enable continuous deployment for your application, you can integrate the AOT compilation into your build pipeline as an optional process.
Project file update
To make the AOT compilation configurable you can use a variable in your project file, as shown below.
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">     <RunAOTCompilation>$(EnableAOTCompilation)</RunAOTCompilation>   </PropertyGroup>
In this case, the AOT compilation will only run if EnableAOTCompilation
is set to ‘true’.
Publish
To enable the AOT compilation with the above changes in place, as part of a simple build script, we could run the following dotnet
command.
dotnet publish -c Release -p:EnableAOTCompilation=true
This will publish in Release mode and set the ‘EnableAOTCompilation’ property to ‘true’.
If you prefer more explicit naming, you can do the following to achieve the same result.
dotnet publish --configuration Release --property:EnableAOTCompilation=true
It is easier to understand the nature of the command-line switches at a glance in this example.
Pipeline
To configure the optional AOT compilation in an Azure DevOps pipeline file, you could set the property via a parameter value, as shown in the following YAML file.
trigger: - main pool:   vmImage: 'ubuntu-latest' parameters: - name: enableAOTCompilation   type: boolean   default: true variables:   BuildConfiguration: Release steps: - task: DotNetCoreCLI@2   inputs:     command: 'publish'     projects: 'src/BlazorDemo/BlazorDemo.Api.csproj' # Path to your main Blazor project.     arguments: '--configuration $(BuildConfiguration) --property:EnableAOTCompilation=${{ parameters.enableAOTCompilation }} --output $(Build.ArtifactStagingDirectory)'   displayName: 'Publish'
Note that the above pipeline file is for illustration purposes only. You will likely want to include several other steps as part of your automated build process such as running tests etc.
In the above example, a ‘DotNetCoreCLI@2’ task has been defined within the ‘steps’ section of the pipeline file.
The task has been configured to call the publish
command for the main Blazor project and the EnableAOTCompilation
property is passed along as an argument, with its value being set according to the enableAOTCompilation
pipeline parameter, which has a default value of true.
As mentioned in a previous section, the main project for an ASP.NET Core Hosted Blazor WebAssembly app will be the back-end API project, otherwise, it is the front-end client project that you should specify for the projects
property.
Summary
In this article, I have covered how to enable ahead-of-time (AOT) compilation for a Blazor WebAssembly application.
I started by discussing some considerations that should be made before deciding to enable AOT compilation for your project, including application size, publish duration, and performance.
I then walked through the changes you need to make in the Blazor WebAssembly project to enable the AOT compilation.
Following this, I explained how to publish your project locally to test it out.
Finally, I looked at how you can optionally enable the AOT compilation as part of a continuous deployment process within an Azure DevOps Pipeline.
Comments