如何缩短ASP.NET Core 7托管Blazor WebAssembly初始加载时间?
ASP.NET Core 7托管式Blazor WebAssembly首屏加载优化方案(已排除预渲染)
问题描述
我用ASP.NET Core 7开发了一个托管式Blazor WebAssembly网站,客户端项目实现了自定义AuthenticationStateProvider,整体包含服务端、共享、基础设施、数据等多个项目。现在遇到的问题是网站启动时首屏加载耗时过长。
客户端Program.cs代码如下:
var builder = WebAssemblyHostBuilder.CreateDefault(args); builder.RootComponents.Add<App>("#app"); builder.RootComponents.Add<HeadOutlet>("head::after"); builder.Services.AddScoped(sp => new HttpClient { BaseAddress = new Uri(builder.HostEnvironment.BaseAddress) }); builder.Services.AddBlazoredSessionStorage(); builder.Services.AddBlazoredToast(); builder.Services.AddAuthorizationCore(); builder.Services.AddScoped<AuthenticationStateProvider, CustomAuthStateProvider>(); await builder.Build().RunAsync();
我尝试过预渲染,但这会破坏现有架构。另外项目中有大量页面,想了解是否有路由懒加载机制可以优化,目前没找到有效方案,请问还有哪些方法能加快初始加载速度?
优化方案
1. 实现路由懒加载(模块拆分)
Blazor WASM支持将非首屏页面拆分为独立的Razor类库(RCL),通过懒加载仅在用户访问对应路由时加载目标程序集,直接减少初始包体积。
具体实现步骤:
- 将非核心页面/组件拆分到单独的RCL项目中,每个RCL对应一个业务模块
- 在主项目的
App.razor中通过LazyAssemblyLoader实现路由级懒加载:
@inject LazyAssemblyLoader AssemblyLoader <Router AppAssembly="@typeof(App).Assembly"> <Found Context="routeData"> @if (routeData.PageType.FullName.StartsWith("YourProject.Features.Order")) { @await LoadAndRenderModule(routeData, "YourProject.Features.Order.dll") } else if (routeData.PageType.FullName.StartsWith("YourProject.Features.User")) { @await LoadAndRenderModule(routeData, "YourProject.Features.User.dll") } else { <RouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)" /> } </Found> <NotFound> <LayoutView Layout="@typeof(MainLayout)"> <p>抱歉,该地址不存在</p> </LayoutView> </NotFound> </Router> @code { private async Task<IComponent> LoadAndRenderModule(RouteData routeData, string assemblyName) { var assemblies = await AssemblyLoader.LoadAssembliesAsync(new[] { assemblyName }); var targetPage = assemblies.SelectMany(a => a.ExportedTypes) .First(t => t == routeData.PageType); return Activator.CreateInstance(targetPage) as IComponent; } }
- 拆分后的RCL需设置
CopyLocalLockFileAssemblies = false,避免依赖重复打包到主程序集
2. 启用AOT编译
在客户端项目的.csproj中开启AOT编译,将IL代码提前编译为机器码,既减少运行时JIT开销,也能显著缩小包体积:
<PropertyGroup> <RunAOTCompilation>true</RunAOTCompilation> </PropertyGroup>
注意:AOT会增加构建时间,且对反射等动态特性有兼容性限制,需提前做兼容性测试。
3. 依赖裁剪与压缩
- 启用响应压缩:在服务端
Program.cs中添加静态文件压缩中间件,降低传输体积:
app.UseHttpsRedirection(); app.UseBlazorFrameworkFiles(); app.UseStaticFiles(); // 启用响应压缩 app.UseResponseCompression();
- 裁剪冗余依赖:检查客户端及共享项目的NuGet包,移除未使用的依赖;对于共享项目,仅引用必要的组件,避免依赖链膨胀。
- 启用代码修剪:在客户端
.csproj中开启链接器,移除未使用的代码:
<PropertyGroup> <BlazorWebAssemblyEnableLinking>true</BlazorWebAssemblyEnableLinking> </PropertyGroup>
4. 优化AuthenticationStateProvider逻辑
自定义认证状态提供者的初始化逻辑可能阻塞首屏渲染,可做如下调整:
- 避免在构造函数中执行耗时的异步认证查询,改为首次访问认证状态时异步加载
- 首屏组件避免同步等待认证状态,改用
CascadingAuthenticationState配合异步渲染,比如显示加载占位符直到认证状态就绪
5. 静态资源缓存优化
- 配置服务端静态文件的长期缓存策略,在
Program.cs中设置:
app.UseStaticFiles(new StaticFileOptions { OnPrepareResponse = ctx => { ctx.Context.Response.Headers.Append( "Cache-Control", "public, max-age=31536000, immutable"); } });
- 将CSS、图片、第三方JS等静态资源部署到CDN,降低用户请求延迟
6. 简化首屏组件
- 首屏仅保留核心UI元素,将侧边栏菜单、非核心统计组件等改为延迟加载
- 避免在首屏组件中初始化大量数据或执行复杂计算,改用异步加载并显示加载状态
内容的提问来源于stack exchange,提问作者Robin Khan
相关产品推荐
相关产品推荐

