ASP.NET Core Blazor WebAssembly 生成工具和预先 (AOT) 编译

注意

此版本不是本文的最新版本。 对于当前版本,请参阅此文的 .NET 8 版本

重要

此信息与预发布产品相关,相应产品在商业发布之前可能会进行重大修改。 Microsoft 对此处提供的信息不提供任何明示或暗示的保证。

对于当前版本,请参阅此文的 .NET 8 版本

本文介绍独立 Blazor WebAssembly 应用的生成工具,以及如何在部署前使用预先 (AOT) 编译来编译应用。

尽管本文主要侧重于独立 Blazor WebAssembly 应用,但有关某些移动设备浏览器堆大小的部分也适用于 Blazor Web 应用的客户端项目 (.Client)。

.NET WebAssembly 生成工具

.NET WebAssembly 生成工具基于 Emscripten,这是一个用于 Web 平台的编译器工具链。 若要安装生成工具,请使用以下任一方法

  • 对于 Visual Studio 安装程序中的 ASP.NET 和 Web 开发工作负载,请从可选组件列表中选择“.NET WebAssembly 生成工具”选项。
  • 在管理命令外壳中执行 dotnet workload install wasm-tools

注意

适用于 .NET 6 项目的 .NET WebAssembly 生成工具

wasm-tools 工作负载为最新版本安装生成工具。 但是,当前版本的生成工具与使用 .NET 6 生成的现有项目不兼容。 使用必须同时支持 .NET 6 和更高版本的生成工具的项目必须使用多目标。

使用 .NET 7 SDK 开发应用时,将 wasm-tools-net6 工作负载用于 .NET 6 项目。 若要安装 wasm-tools-net6 工作负载,请从管理命令 shell 执行以下命令:

dotnet workload install wasm-tools-net6

预先 (AOT) 编译

Blazor WebAssembly 支持预先 (AOT) 编译,你可以直接将 .NET 代码编译到 WebAssembly 中。 AOT 编译会提高运行时性能,代价是应用大小增加。

如果没有启用 AOT 编译,则 Blazor WebAssembly 应用使用在 WebAssembly 中实现的 .NET 中间语言 (IL) 解释器在浏览器上运行,该解释器包括部分即时 (JIT) 运行时支持(其非正式名称为 Jiterpreter)。 由于 .NET IL 代码已经过解释,因此应用的运行速度通常比在没有任何 IL 解释的服务器端 .NET JIT 运行时上要慢。 AOT 编译将应用的 .NET 代码直接编译到 WebAssembly 中来供浏览器进行本机 WebAssembly 执行,从而处理这一性能问题。 AOT 性能改进可使执行 CPU 密集型任务的应用得到极大改进。 使用 AOT 编译的缺点是,AOT 编译的应用通常比其 IL 解释的对应项要长,因此通常在被首次请求时,下载到客户端的速度通常更慢。

如果没有启用 AOT 编译,则 Blazor WebAssembly 应用使用在 WebAssembly 中实现的 .NET 中间语言 (IL) 解释器在浏览器上运行。 由于 .NET 代码已经过解释,因此应用的运行速度通常比在服务器端 .NET 即时 (JIT) 运行时上要慢。 AOT 编译将应用的 .NET 代码直接编译到 WebAssembly 中来供浏览器进行本机 WebAssembly 执行,从而处理这一性能问题。 AOT 性能改进可使执行 CPU 密集型任务的应用得到极大改进。 使用 AOT 编译的缺点是,AOT 编译的应用通常比其 IL 解释的对应项要长,因此通常在被首次请求时,下载到客户端的速度通常更慢。

有关安装 .NET WebAssembly 生成工具的指导,请参阅 ASP.NET Core Blazor WebAssembly 生成工具和预先 (AOT) 编译

若要启用 WebAssembly AOT 编译,请将设置为 true<RunAOTCompilation> 属性添加到 Blazor WebAssembly 应用的项目文件中:

<PropertyGroup>
  <RunAOTCompilation>true</RunAOTCompilation>
</PropertyGroup>

若要将应用编译到 WebAssembly,请发布应用。 发布 Release 配置可确保 .NET 中间语言 (IL) 链接也运行来减少已发布的应用的大小:

dotnet publish -c Release

仅当项目发布时,才执行 WebAssembly AOT 编译。 在开发期间(Development 环境)运行项目时,不会使用 AOT 编译,理由是 AOT 编译处理小项目时通常用时几分钟,而处理更大项目时,耗时可能长得多。 对于未来版本的 ASP.NET Core,正在开发减少 AOT 编译生成时间的功能。

AOT 编译的 Blazor WebAssembly 应用的大小通常比编译到 .NET IL 中的应用大小要大:

  • 虽然大小差异取决于应用,则大多数 AOT 编译的应用大约是其 IL 编译的版本的两倍大。 这意味着使用 AOT 编译是用加载时间性能换取运行时性能。 使用 AOT 编译是否值得进行这种权衡取决于你的应用。 CPU 密集型的 Blazor WebAssembly 应用通常从 AOT 编译中受益最大。

  • AOT 编译的应用大小较大,是由于两个条件导致的:

    • 需要更多代码来表示本机 WebAssembly 中的高级 .NET IL 指令。
    • 在应用发布时,AOT 不会剪裁掉托管的 DLL。 Blazor 需要 DLL 来收集反射元数据并支持某些 .NET 运行时功能。 在客户端上要求使用 DLL 会增加下载大小,但会提供更兼容的 .NET 体验。

注意

若要了解 Mono/WebAssembly MSBuild 属性和目标,请参阅 WasmApp.Common.targetsdotnet/runtime GitHub 存储库)。 根据文档 Blazor MSBuild 配置选项 (dotnet/docs #27395) 计划常见 MSBuild 属性的官方文档。

在预先编译 (AOT) 后剪裁 .NET IL

借助 WasmStripILAfterAOT MSBuild 选项,可以在对 WebAssembly 执行 AOT 编译后移除已编译方法的 .NET 中间语言 (IL),这会减小 _framework 文件夹的大小。

在应用的项目文件中,执行以下操作:

<PropertyGroup>
  <RunAOTCompilation>true</RunAOTCompilation>
  <WasmStripILAfterAOT>true</WasmStripILAfterAOT>
</PropertyGroup>

此设置会剪裁大多数已编译方法的 IL 代码,包括库中的方法和应用中的方法。 并非所有已编译的方法都可以剪裁,因为 .NET 解释器在运行时仍然需要一些方法。

若要报告剪裁选项的问题,请在 dotnet/runtime GitHub 存储库上提出问题。

如果它阻止应用正常运行,请禁用剪裁属性:

<WasmStripILAfterAOT>false</WasmStripILAfterAOT>

某些移动设备浏览器的堆大小

生成在客户端上运行并面向移动设备浏览器(尤其是 iOS 上的 Safari)的 Blazor 应用时,可能需要使用 MSBuild 属性 EmccMaximumHeapSize 减少应用的最大内存。 有关详细信息,请参阅托管和部署 ASP.NET Core Blazor WebAssembly

运行时重新链接

Blazor WebAssembly 应用最大的组成部分之一是基于 WebAssembly 的 .NET 运行时 (dotnet.wasm),当用户的浏览器首次访问该应用时,浏览器必须下载它。 重新链接 .NET WebAssembly 运行时会剪裁未使用的运行时代码,从而提高下载速度。

运行时重新链接需要安装 .NET WebAssembly 生成工具。 有关详细信息,请参阅用于 ASP.NET Core Blazor 的工具

安装 .NET WebAssembly 生成工具后,在 Release 配置中发布应用时,会自动执行运行时重新链接。 禁用全局化时,减少的大小尤其显著。 有关详细信息,请参阅 ASP.NET Core Blazor 全球化和本地化

重要

运行时重新链接会剪裁类实例 JavaScript 可调用的 .NET 方法,除非这些方法受到保护。 有关详细信息,请参阅在 ASP.NET Core Blazor 中从 JavaScript 函数调用 .NET 方法

Single Instruction, Multiple Data (SIMD)

WebAssembly Single Instruction, Multiple Data (SIMD) 可以通过使用单个指令对多个数据片段并行执行操作来提高矢量化计算的吞吐量。 SIMD 默认启用。

若要禁用 SIMD(例如,在面向旧浏览器或不支持 SIMD 的移动设备上的浏览器时这样做),请在应用的项目文件 (.csproj) 中将 <WasmEnableSIMD> 属性设置为 false

<PropertyGroup>
  <WasmEnableSIMD>false</WasmEnableSIMD>
</PropertyGroup>

有关详细信息,请参阅配置和托管 .NET WebAssembly 应用程序:SIMD - 单指令,多数据,并请注意,该指南没有进行版本控制,适用于最新的公开版本。

WebAssembly Single Instruction, Multiple Data (SIMD) 可以通过使用单个指令对多个数据片段并行执行操作来提高矢量化计算的吞吐量。 默认禁用 SIMD。

若要启用 SIMD,请在应用的项目文件 (.csproj) 中将 <WasmEnableSIMD> 属性设置为 true

<PropertyGroup>
  <WasmEnableSIMD>true</WasmEnableSIMD>
</PropertyGroup>

有关详细信息,请参阅配置和托管 .NET WebAssembly 应用程序:SIMD - 单指令,多数据,并请注意,该指南没有进行版本控制,适用于最新的公开版本。

异常处理

异常处理在默认情况下处于启用状态。 若要禁用异常处理,请在应用的项目文件 (.csproj) 中添加值为 false<WasmEnableExceptionHandling> 属性:

<PropertyGroup>
  <WasmEnableExceptionHandling>false</WasmEnableExceptionHandling>
</PropertyGroup>

若要启用 WebAssembly 异常处理,请在应用的项目文件 (.csproj) 中添加值为 true<WasmEnableExceptionHandling> 属性:

<PropertyGroup>
  <WasmEnableExceptionHandling>true</WasmEnableExceptionHandling>
</PropertyGroup>

其他资源