November 29, 2022
The .NET WebAssembly build tool is used to compile .NET code to WebAssembly (WASM) and other runtime features. This blog will take you through the different features with the .NET WebAssembly build tool and new features to help you build performant, powerful .NET apps using WASM. It is based on Emscripten, it compiles languages that use LLVM (low level virtual machine), into WebAssembly.
At the time of writing this document, there are 3 different versions:
1. wasm-tools: Used for Ahead-of-time compilation, runtime relinking etc.
2. wasm-tools-net6: Addressing incompatibility issues for .NET 6 projects running on .NET 7 SDK
It can be installed by running the relevant command in a terminal:
Even though Ahead-of-time (AOT) compilation is an existing feature in .NET 6, I feel it is still worth mentioning. Enabling this feature will compile .NET code to WASM and result in runtime performance improvement.
To enable add RunAOTCompilation property and set the value to true in the project file:
Publishing the app with the Release configuration ensures that .NET Intermediate Language linking runs to reduce the size of the published app.
WebAssembly Single Instruction Multiple Data (SIMD) is available when a project enables AOT. It is a new feature in .NET 7, for developers who develop applications with compute-intensive needs i.e. gaming, image processing etc. SIMD is a technique to speed up calculations. It works on multiple data within a single CPU instruction where multithreading works on multiple data in different threads. This blog by Rober Aboukhalil has more detailed information.
SIMD is supported when AOT is enabled (except for in the Apple Safari browser). To enable this feature add the WasmEnableSIMD property and set the value to true in the project file:
The dotnet.wasm .NET runtime must be downloaded when the user accesses the app for the first time. This feature reduces the size of the dotnet.wasm file by trimming unused runtime code. It happens automatically when the app is published in Release config. By disabling globalization in the project, the reduction is even more exorbitant. Runtime relinking was introduced in .NET 6.
Create a new WebAssembly Browser App template by running:
Two experimental project templates are available after installing the experimental workload:
- WebAssembly Browser App
- WebAssembly Console App
The following section is an overview of this feature.
dotnet.js contains APIs that enables named modules to be created and then imported into C# code. These modules then call into methods exposed by your .NET app.
Setup the .NET WebAssembly runtime:
A module that can be called from .NET by using setModuleImports is required. The first parameter is the module name (main.js) and the second parameter is the name of the method.
Setup the .NET WebAssembly runtime in JS and run the program
The JSExport attribute exports a .NET method and can be imported into JS. In C# decorate a method with JSExport attribute.
You need to follow the instructions set out in the Readme.md file that is created when creating the app.
This is what you will see in the browser when you run the above code:
There is a fantastic detailed Microsoft devblog from Pavel Savara around this topic.
It is inspiring to see these new inventions and I am excited about the possibilities these features create.