Lazy-loading Blazor WebAssembly feature assemblies
Blazor WebAssembly apps can ship too much code upfront. Lazy-loading feature assemblies with <LazyLoad> reduces initial bundle size and speeds first paint, at the cost of extra network requests.
27 Jan 2026, 03:43 UTC

Blazor WebAssembly apps typically ship all compiled code in a single bundle. On a typical app with dozens of pages and components, that first download can exceed 2 MB, delaying interactive content on slow connections. Lazy-loading splits the app into a small core bundle that loads at startup and larger feature bundles that the router fetches only when a user navigates to that route.
How lazy-loading splits core and feature assemblies
The core bundle contains the Blazor framework, shared static assets, and any code needed for the initial route. Feature assemblies are compiled separately and marked for lazy-loading via a project-level flag. When the router encounters a route assigned to a feature, it triggers a dynamic import of the corresponding WebAssembly module, which the browser fetches, compiles, and integrates at runtime. This means the initial payload stays small, and code for rarely-used screens never travels over the wire until needed.
Configuring <LazyLoad> and the router
Enabling lazy-loading involves two steps: marking the feature project and configuring the root router.
<Project 'FeatureA' /><PropertyGroup><TargetFramework>net8.0</TargetFramework><BlazorWebAssemblyEnableLazyLoad>true</BlazorWebAssemblyEnableLazyLoad></PropertyGroup></Project>In the root App.razor (or custom router component), the <Router> element receives an AppAssembly parameter and an OnNavigateAsync callback that resolves the feature name and calls NavigationManager.NavigateToAsync:
<Router AppAssembly='typeof(App).Assembly' OnNavigateAsync='LoadFeatureAsync' /><code>@code { private async Task LoadFeatureAsync(string featureName, NavigationCommand command) { await NavigationManager.NavigateToAsync('/' + featureName, true); }}</code>These changes go in a Visual Studio solution with a Blazor WebAssembly project targeting .NET 8 or later. No special permissions beyond write access to the project files are required.Measuring the performance impact
- Run the app locally (dotnet run or F5 in Visual Studio).
- Open Chrome DevTools to Network tab.
- Clear the cache and reload. Observe that only the core bundle (e.g., blazor.webassembly.js and the core .dlls) is downloaded initially.
- Navigate to a route mapped to a lazy-loaded feature. A new network request for the feature assembly appears.
- Navigate again to the same feature; the assembly is served from the browser cache, and no additional request is made.
The Performance panel should show a reduced Time to First Paint (TTFP) compared to the non-lazy-loaded baseline. The Network tab should confirm the initial payload size and the on-demand request pattern.
Limitations and what to watch
- Each feature bundle adds an HTTP request. On strict Content-Security-Policy configurations or limited bandwidth, extra requests can become a bottleneck.
- The first navigation to a lazy-loaded feature incurs a noticeable delay. Users may see a loading spinner unless the feature is pre-loaded or prefetched.
- Debugging is more complex because source maps for lazy-loaded assemblies are not available until after the bundle is fetched, making breakpoints harder to set during early development.
After implementing lazy-loading, compare the initial bundle size (via the Size column in DevTools Network) against a non-lazy baseline. Verify that subsequent navigations reuse the cached assembly by checking the Cache column. If CSP blocks the Fetch API, adjust policy to allow blob: or https: as needed.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.