如果你正在用 Blazor 开发 .NET 全栈应用,是否曾感觉工具链的体验有些割裂?Visual Studio 很强大,但启动慢、资源占用高;VS Code 轻快,但配置 Blazor 开发环境总得折腾一番插件和命令。更不用说那些隐藏在项目文件(.csproj)和命令行参数背后的构建、调试、发布细节,一旦出问题,排查起来就像在迷宫里打转。
这不是你一个人的感受。Blazor 作为微软力推的 .NET 全栈解决方案,其核心价值在于让开发者用 C# 统一前后端。但如果工具链(Tooling)不顺手、不透明,这种“统一”的体验就会大打折扣。你写的 C# 代码如何变成浏览器中运行的 WebAssembly?热重载(Hot Reload)为什么有时灵有时不灵?发布到生产环境时,有哪些配置项能显著影响首屏加载速度?
本文将深入解读 ASP.NET Core Blazor 的官方工具链(Tooling),但不止于翻译文档。我们会聚焦于一个核心判断:Blazor 工具链的进化方向,正从“提供功能”转向“优化体验”,其关键是通过更智能的元数据(Meta Tooling)和更统一的命令行接口,降低从开发到部署的全流程认知负担。无论你是刚接触 Blazor,还是已经用它做过项目,本文将帮你:
- 厘清 Blazor 项目从创建、开发、调试到发布的核心工具与流程。
- 掌握
dotnetCLI 中那些对 Blazor 开发至关重要的命令和参数。 - 理解并配置影响开发体验的“元工具”,如热重载、Razor 组件编译等。
- 学会优化生产构建,解决常见的部署问题。
我们将避开空泛的概念,直接进入实战场景,用代码和配置说话。
1. Blazor Tooling 的核心:它到底解决了什么痛点?
在传统 Web 开发中,前端(JavaScript/TypeScript + 框架)和后端(.NET/Java 等)通常使用两套独立的工具链:前端有 npm/yarn、Webpack/Vite、ESLint;后端有 dotnet CLI、MSBuild、NuGet。开发者需要频繁在两种思维模式和两套命令间切换。
Blazor 的愿景是用 .NET 统一全栈。因此,其工具链的核心目标就是:让开发者能够主要使用 .NET 生态的工具(尤其是dotnetCLI)来完成整个 Web 应用的生命周期管理。这解决了几个关键痛点:
- 环境统一:不需要单独安装和配置 Node.js、npm 就能进行前端开发(对于 Blazor WebAssembly,可能需要用于调试代理,但非必须)。
- 语言一致:代码分析、格式化、重构(通过 Roslyn)在 Razor 组件(
.razor)和 C# 后端代码中保持一致。 - 构建一体化:一个
dotnet build命令同时处理服务端代码、Razor 组件编译、静态资源处理(如 CSS 隔离)等。 - 调试无缝:在 Visual Studio 或配置好的 VS Code 中,可以直接在 C# 代码和 Razor 组件中设置断点,进行无缝调试,无论代码最终运行在服务器(Blazor Server)还是浏览器(Blazor WebAssembly)。
然而,工具链的“统一”并非没有代价。它把复杂性封装在了dotnetCLI、MSBuild 任务和项目文件里。如果你不了解这些底层机制,当遇到构建失败、热重载失效、发布包体积过大等问题时,就会束手无策。
因此,理解 Blazor Tooling,不仅仅是学会几个命令,更是要理解其背后的工作流程和配置点。这是从“会用”到“精通”的关键一步。
2. 核心概念与工具链全景
在深入实操前,我们先明确几个关键概念和工具链的组成部分。
2.1 两种托管模型与工具链差异
Blazor 有两种主要托管模型,它们的工具链在开发和构建阶段有显著不同:
Blazor Server:
- 运行时:组件在服务器端的 .NET 运行时中执行,UI 更新通过 SignalR 连接实时发送到客户端。
- 工具链重点:更偏向传统的 ASP.NET Core 应用。开发时依赖服务端运行和热重载。构建产出主要是服务端的 DLL 和客户端的少量引导脚本。
- 调试:主要在后端进行,类似于调试 MVC 或 Razor Pages 应用。
Blazor WebAssembly (WASM):
- 运行时: .NET 运行时(精简版)和你的应用代码都被编译成 WebAssembly,在浏览器中直接运行。
- 工具链重点: 引入了AOT(Ahead-of-Time)编译、修剪(Trimming)、压缩等针对客户端交付的优化步骤。构建过程更复杂,涉及将 .NET IL 转换为 WASM。
- 调试: 需要浏览器支持 .NET 调试,或通过详细的日志和浏览器开发者工具进行。
工具链选择的影响:你创建项目时的选择(blazorserver或blazorwasm模板),决定了后续dotnetCLI 命令内部调用的 MSBuild 目标和任务。
2.2 工具链核心组件
| 组件 | 作用 | 关键命令/文件 |
|---|---|---|
dotnetCLI | 核心命令行工具,用于创建、构建、运行、发布、管理依赖等。 | dotnet new,dotnet build,dotnet run,dotnet publish,dotnet watch |
| MSBuild | 构建引擎,解析.csproj文件,执行编译、打包等任务。 | YourProject.csproj文件 |
| NuGet | 包管理器,用于恢复项目依赖。 | dotnet restore,NuGet.Config |
| Razor 编译器 | 将.razor和.cshtml文件编译成 C# 类。 | 集成在构建过程中,可通过RazorCompileOnBuild等属性配置。 |
| 热重载 (Hot Reload) | 在应用运行时,将代码更改实时注入,无需重启应用。 | dotnet watch命令的核心功能。 |
| ASP.NET Core 运行时 | 为 Blazor Server 应用提供执行环境,或为 Blazor WASM 提供开发时服务端主机。 | 通过Microsoft.AspNetCore.App等包引用。 |
2.3 理解“元工具(Meta Tooling)”
“Meta Tooling”指的是那些配置、控制或增强核心开发工具行为的工具或设置。在 Blazor 上下文中,它主要包括:
- 项目文件(
.csproj)中的 MSBuild 属性:例如<BlazorWebAssemblyLoadAllGlobalizationData>true</BlazorWebAssemblyLoadAllGlobalizationData>控制 WASM 应用的全球化数据加载。 launchSettings.json:定义不同启动配置文件(Profile),控制应用启动方式、环境变量、URL 等。appsettings.json与环境配置:管理应用配置,影响运行时行为。- IDE/编辑器配置:如
.vscode/launch.json、.vscode/tasks.json用于配置 VS Code 的调试和任务。 dotnet watch的过滤规则:控制哪些文件变动会触发热重载或重启。
掌握这些“元工具”,意味着你能精细地控制开发体验和构建输出,而不是仅仅使用默认设置。
3. 环境准备与项目创建
3.1 环境要求
- .NET SDK: 确保安装最新稳定版 .NET SDK(例如 .NET 8 或 .NET 9 Preview)。Blazor 的新特性通常需要对应版本的 SDK。你可以通过命令行检查:
dotnet --list-sdks - IDE/编辑器(二选一或都备):
- Visual Studio 2022+: 社区版免费。安装时务必勾选“ASP.NET 和 Web 开发”工作负载。它提供了最完整的 Blazor 开发体验(可视化设计器、高级调试、热重载UI)。
- Visual Studio Code: 轻量级选择。需要安装以下扩展:
C#(由 Microsoft 发布)C# Dev Kit(可选,但提供更丰富的项目管理体验)Live Preview(用于预览静态内容,非必须)
3.2 使用 CLI 创建第一个 Blazor 项目
我们摒弃 GUI,从最本质的命令行开始,理解项目结构的来源。
打开终端,执行以下命令创建一个 Blazor WebAssembly 独立应用:
# 创建一个名为 BlazorToolingDemo 的 Blazor WebAssembly 项目 dotnet new blazorwasm -n BlazorToolingDemo -o BlazorToolingDemo # 进入项目目录 cd BlazorToolingDemo命令参数解读:
dotnet new: 项目模板创建命令。blazorwasm: 模板简称。对应 Blazor WebAssembly 独立托管模型。如果要创建 Blazor Server 项目,使用blazorserver。-n BlazorToolingDemo: 指定项目名称。-o BlazorToolingDemo: 指定输出目录。
创建完成后,用 VS Code 或你喜欢的编辑器打开该目录。你会看到如下核心结构:
BlazorToolingDemo/ ├── Program.cs // 应用入口点 ├── BlazorToolingDemo.csproj // 项目文件,工具链配置的核心 ├── Properties/ │ └── launchSettings.json // 启动配置(元工具) ├── wwwroot/ // 静态资源(CSS, JS, 图片等) ├── Pages/ // 路由组件(如 Counter.razor, FetchData.razor) ├── Components/ // 可复用的 UI 组件 ├── Layout/ // 布局组件 └── Shared/ // 其他共享组件或类关键文件BlazorToolingDemo.csproj初探:
<Project Sdk="Microsoft.NET.Sdk.BlazorWebAssembly"> <PropertyGroup> <TargetFramework>net8.0</TargetFramework> <Nullable>enable</Nullable> <ImplicitUsings>enable</ImplicitUsings> </PropertyGroup> <ItemGroup> <PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly" Version="8.0.0" /> <PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.DevServer" Version="8.0.0" PrivateAssets="all" /> </ItemGroup> </Project>注意第一行:Sdk="Microsoft.NET.Sdk.BlazorWebAssembly"。这个 SDK 属性是最重要的元工具配置之一,它告诉 MSBuild:“请使用专门为 Blazor WebAssembly 定制的构建逻辑”。这背后包含了处理 WASM 编译、静态资源、调试代理等大量预设任务。
4. 开发工作流核心:构建、运行与监控
4.1 基础构建与运行
# 恢复 NuGet 包依赖(通常在 build 或 run 时会自动执行) dotnet restore # 编译项目 dotnet build # 运行项目(使用 launchSettings.json 中的第一个配置,通常是 https) dotnet run # 运行项目并指定特定配置(如 HTTP) dotnet run --launch-profile "http"运行后,控制台会输出应用监听的 URL(如https://localhost:7279和http://localhost:5279),用浏览器打开即可。
4.2 使用dotnet watch实现热重载开发
这是提升开发效率的关键命令。它不仅会自动重启应用,还支持 .NET 的热重载功能,允许你在不重启应用的情况下,修改 C# 和 Razor 代码并立即看到效果。
# 启动应用并监控文件变化 dotnet watch run现在,尝试修改Pages/Counter.razor文件中的计数增量,比如把currentCount++改为currentCount += 2,保存文件。观察浏览器和终端,你会发现页面自动更新了,而应用进程并未重启(热重载生效)。如果修改了需要重新编译程序集的核心逻辑,watch会自动触发重建和重启。
dotnet watch的过滤配置: 你可以在项目文件中控制watch的行为。例如,忽略wwwroot下某些文件的变动,避免不必要的重启。
<ItemGroup> <Watch Include="**\*.razor;**\*.cs;**\*.cshtml" Exclude="**\*.min.js;**\*.min.css;wwwroot\lib\**" /> </ItemGroup>4.3 调试配置详解
Visual Studio: 开箱即用。只需按 F5 或点击调试按钮,它会自动读取launchSettings.json并附加调试器。
Visual Studio Code: 需要手动配置。在项目根目录创建.vscode/launch.json文件:
{ "version": "0.2.0", "configurations": [ { "name": "Launch and Debug Blazor WASM", "type": "coreclr", "request": "launch", "preLaunchTask": "build", "program": "${workspaceFolder}/bin/Debug/net8.0/BlazorToolingDemo.dll", "args": [], "cwd": "${workspaceFolder}", "stopAtEntry": false, "serverReadyAction": { "action": "openExternally", "pattern": "\\bNow listening on:\\s+(https?://\\S+)" }, "env": { "ASPNETCORE_ENVIRONMENT": "Development" } } ] }同时,创建.vscode/tasks.json来定义构建任务:
{ "version": "2.0.0", "tasks": [ { "label": "build", "command": "dotnet", "type": "process", "args": [ "build", "${workspaceFolder}/BlazorToolingDemo.csproj", "/property:GenerateFullPaths=true", "/consoleloggerparameters:NoSummary" ], "problemMatcher": "$msCompile" } ] }配置好后,在 VS Code 中按 F5 即可启动调试。对于 Blazor WASM,浏览器端 C# 代码的调试需要更复杂的配置(通常需要 Chrome 或 Edge 的特定扩展和启用脚本调试),在开发初期,利用服务端日志和浏览器控制台通常是更高效的方式。
5. 深入项目文件:配置构建与发布行为
.csproj文件是控制 Blazor 工具链的“中枢”。下面我们看几个关键配置。
5.1 控制 WebAssembly 构建行为(Blazor WASM)
<Project Sdk="Microsoft.NET.Sdk.BlazorWebAssembly"> <PropertyGroup> <TargetFramework>net8.0</TargetFramework> <!-- 启用 AOT 编译:大幅提升运行时性能,但显著增加构建时间和输出大小 --> <RunAOTCompilation>true</RunAOTCompilation> <!-- 启用修剪:移除未使用的代码,减小包体积,但需小心运行时反射失败 --> <PublishTrimmed>true</PublishTrimmed> <!-- 设置修剪粒度:默认为 link,可设为 copyused 以尝试保留更多 --> <TrimMode>link</TrimMode> <!-- 加载所有全球化数据:增加包体积,但确保所有区域文化信息可用 --> <BlazorWebAssemblyLoadAllGlobalizationData>false</BlazorWebAssemblyLoadAllGlobalizationData> <!-- 启用压缩(Brotli/Gzip):减小传输体积 --> <BlazorEnableCompression>true</BlazorEnableCompression> <!-- 定义运行时标识符,用于发布特定平台运行时(如 Linux) --> <RuntimeIdentifier>linux-x64</RuntimeIdentifier> </PropertyGroup> </Project>性能与体积的权衡:
<RunAOTCompilation>: 对于计算密集型应用(如图像处理、游戏)提升巨大,但首次构建可能非常慢(几分钟到十几分钟),且.dll文件会编译成.aot文件,发布体积可能增加数 MB。建议在性能瓶颈明确时启用,开发阶段关闭。<PublishTrimmed>: 是减小 WASM 应用体积的最有效手段。但 .NET 的修剪器是“保守”的,它可能无法识别通过反射动态加载的类型。如果你的代码大量使用反射、动态加载或某些序列化库(如System.Text.Json在某些复杂场景),启用修剪可能导致运行时错误。务必在启用后进行全面测试。
5.2 控制 Blazor Server 的构建行为
Blazor Server 项目文件通常更简单,因为大部分逻辑在服务端。
<Project Sdk="Microsoft.NET.Sdk.Web"> <PropertyGroup> <TargetFramework>net8.0</TargetFramework> <!-- 启用 Razor 组件在构建时编译,而不是运行时编译 --> <RazorCompileOnBuild>true</RazorCompileOnBuild> <!-- 启用 Razor 组件的热重载 --> <HotReloadEnabled>true</HotReloadEnabled> </PropertyGroup> </Project>5.3 管理静态资源与 NPM 包
虽然 Blazor 旨在减少对前端工具链的依赖,但有时仍需要引入 JavaScript 库或使用 CSS 预处理器。
1. 使用 LibMan(库管理器): .NET 生态内管理前端库的工具。
# 初始化 LibMan 配置文件 dotnet tool install -g Microsoft.Web.LibraryManager.Cli libman init -p cdnjs这会在项目根目录创建libman.json。你可以编辑它来添加库,例如 jQuery:
{ "version": "1.0", "defaultProvider": "cdnjs", "libraries": [ { "library": "jquery@3.6.0", "destination": "wwwroot/lib/jquery/" } ] }然后运行libman restore或通过 Visual Studio 的上下文菜单恢复。
2. 在 Razor 组件/布局中引用:
<!-- 在 _Layout.razor 或 _Host.cshtml 的 <head> 中 --> <script src="_content/BlazorToolingDemo/lib/jquery/jquery.min.js"></script>注意路径中的_content/{AssemblyName},这是 Blazor 从类库或本项目引用静态资源的标准方式。
3. 使用 NPM/Webpack 等高级工作流: 对于复杂场景,你可以创建独立的package.json和构建脚本,并在.csproj中添加 MSBuild 目标,在构建前后执行npm命令。但这超出了基础工具链范围,需要更深入的工程化配置。
6. 发布与部署:从开发到生产
开发完成后的最终步骤是发布。dotnet publish命令是核心。
6.1 基础发布命令
# 发布到 ./publish 目录,使用 Release 配置(会进行优化) dotnet publish -c Release -o ./publish # 针对特定运行时环境发布 (Blazor WASM 通常不需要,除非包含服务端) dotnet publish -c Release -r linux-x64 --self-contained true -o ./publish-linux对于Blazor WebAssembly:
publish输出主要包含wwwroot目录下的所有文件(包括压缩后的.dll、.wasm、.js等),以及一个web.config或.htaccess示例文件(用于配置服务器正确处理 WASM MIME 类型)。- 你需要将
publish目录下的所有内容部署到任何支持静态文件服务的 Web 服务器(如 IIS、Nginx、Apache、Azure Storage Static Website 等)。
对于Blazor Server:
publish输出是一个完整的 ASP.NET Core 应用程序,包含服务端可执行文件或 DLL。你需要将其部署到支持 .NET 运行时的服务器(如 IIS、Kestrel on Linux、Azure App Service 等)。
6.2 优化发布输出
发布配置(-c Release)会自动启用一些优化。你还可以在项目文件中或通过命令行参数进行微调:
# 发布时启用 AOT 编译和修剪(如果项目文件中已配置,这里会生效) dotnet publish -c Release -p:RunAOTCompilation=true -p:PublishTrimmed=true -o ./publish-optimized检查发布输出:发布后,查看./publish/wwwroot/_framework目录。你会看到blazor.boot.json(引导文件)、压缩后的程序集(.gz,.br)、以及可能存在的.aot文件。使用浏览器开发者工具的“网络”选项卡,查看文件加载大小和压缩情况。
6.3 配置服务器
IIS: 确保已安装 ASP.NET Core 托管捆绑包。在 IIS 中创建站点,物理路径指向publish文件夹。通常无需额外配置,因为web.config已包含。
Nginx: 需要配置正确的 MIME 类型和尝试文件规则。
server { listen 80; server_name your_domain.com; location / { root /var/www/blazor_app; # 你的发布目录 try_files $uri $uri/ /index.html =404; # 支持客户端路由 } # 配置 WASM 和 DLL 的 MIME 类型 location ~ \\.wasm$ { add_header Content-Type application/wasm; } location ~ \\.dll$ { add_header Content-Type application/octet-stream; } }7. 常见问题与排查思路
Blazor 工具链问题多集中在构建、热重载和发布阶段。
| 问题现象 | 可能原因 | 排查方式 | 解决方案 |
|---|---|---|---|
dotnet build失败,错误 CSxxxx | 1. 语法错误。 2. 缺少 NuGet 包引用。 3. 目标框架不匹配。 | 1. 查看错误信息具体行号。 2. 运行 dotnet restore并检查csproj文件。3. 检查 TargetFramework是否与 SDK 版本兼容。 | 1. 修复代码错误。 2. 添加正确的 <PackageReference>。3. 升级 SDK 或修改目标框架。 |
dotnet watch run不触发热重载 | 1. 文件不在监控范围内。 2. 代码更改类型不支持热重载。 3. 项目文件配置了 Watch排除。 | 1. 确认修改的是.razor,.cs等文件。2. 查看终端输出,是否有“无法应用热重载”的警告。 3. 检查 .csproj中的<Watch>项。 | 1. 确保文件类型正确。 2. 某些结构性更改(如添加方法签名)需要重启。 3. 调整 <Watch>配置或使用dotnet watch run --non-interactive查看详细日志。 |
| Blazor WASM 应用发布后,浏览器控制台报错“Failed to fetch...”或“Could not load...” | 1. 服务器未正确配置 WASM/DLL MIME 类型。 2. 文件路径错误(如子目录部署)。 3. 修剪(Trimming)导致运行时缺少必要程序集。 | 1. 检查浏览器网络面板,看哪个文件加载失败(404 或 403)。 2. 确认 blazor.boot.json中的资源路径是否正确。3. 在开发环境发布测试(关闭修剪),对比文件列表。 | 1. 按第6.3节配置服务器 MIME 类型。 2. 确保应用部署在网站根目录,或正确配置 <base href>。3. 在项目文件中为特定包禁用修剪: <TrimmerRootAssembly Include="Your.Assembly" />,或使用DynamicDependency特性。 |
| Blazor Server 应用出现连接断开(Circuit disconnected) | 1. 网络不稳定。 2. 服务器内存/CPU 过载。 3. 长时间无操作,会话超时。 4. 服务器端异常导致电路终止。 | 1. 检查客户端网络和服务器资源监控。 2. 查看服务器端日志(如 Console或ILogger输出)。3. 在开发者工具中查看 WebSocket 连接状态。 | 1. 优化代码,避免长时间同步操作阻塞电路。 2. 增加 CircuitOptions中的DisconnectedCircuitRetentionPeriod。3. 实现重连逻辑(Blazor 框架已提供基础支持)。 4. 确保服务端代码进行异常处理。 |
| 启用 AOT 编译后,构建时间极长 | AOT 编译本身是计算密集型过程。 | 正常现象。 | 1. 开发阶段关闭 AOT (<RunAOTCompilation>false</RunAOTCompilation>)。2. 仅在发布生产版本时启用。 3. 考虑使用更强大的构建机器。 |
在 Linux/macOS 上运行dotnet run提示找不到 SDK | 1. 未安装 .NET SDK。 2. 多版本 SDK 存在,未使用正确版本。 3. 环境变量 PATH未设置。 | 运行dotnet --info查看已安装的 SDK。 | 1. 从官网安装对应系统的 .NET SDK。 2. 使用 global.json文件锁定项目所需的 SDK 版本。 |
8. 最佳实践与工程建议
版本控制与
.gitignore:- 将
bin/,obj/,publish/等目录添加到.gitignore。 - 考虑忽略
.vs/,*.user等 IDE 特定文件。 - 对于 Blazor WASM,
wwwroot/_framework下的编译输出也不应入版本库。
- 将
使用
global.json锁定 SDK 版本: 在解决方案根目录创建global.json,确保团队所有成员使用相同的 SDK 版本,避免因版本差异导致的构建问题。{ "sdk": { "version": "8.0.100", "rollForward": "patch" } }分层配置
launchSettings.json: 为不同环境(开发、测试、生产)创建不同的启动配置文件,预设环境变量、URL 等。"profiles": { "BlazorToolingDemo": { "commandName": "Project", "dotnetRunMessages": true, "launchBrowser": true, "applicationUrl": "https://localhost:7279;http://localhost:5279", "environmentVariables": { "ASPNETCORE_ENVIRONMENT": "Development" } }, "ProductionSim": { "commandName": "Project", "dotnetRunMessages": false, "launchBrowser": true, "applicationUrl": "http://localhost:5000", "environmentVariables": { "ASPNETCORE_ENVIRONMENT": "Production" } } }为 Blazor WASM 启用压缩并配置服务器缓存: 在
Program.cs中确保使用了压缩,并在服务器上为.br(Brotli) 和.gz文件设置长期缓存头,大幅提升重复访问性能。谨慎使用修剪(Trimming):
- 始终在启用修剪的情况下,运行完整的集成测试和端到端测试。
- 使用
<TrimmerRootAssembly>或[DynamicDependency]特性来保留必要的程序集。 - 考虑使用
<IsTrimmable>false</IsTrimmable>为某些明确不兼容的库禁用修剪。
监控与日志:
- 在 Blazor Server 中,充分利用
ILogger记录电路生命周期事件和异常。 - 在 Blazor WASM 中,可以将日志发送到服务器端,或使用
console.log拦截器在浏览器控制台输出结构化日志。
- 在 Blazor Server 中,充分利用
持续集成/持续部署 (CI/CD) 集成:
- 在 CI 流水线中,使用
dotnet restore --locked-mode确保依赖一致。 - 使用
dotnet publish -c Release -p:UseAppHost=true生成可执行文件(如需要)。 - 将发布产物作为流水线制品,供后续部署步骤使用。
- 在 CI 流水线中,使用
Blazor 的工具链是连接 .NET 开发理念与现代化 Web 体验的桥梁。它封装了复杂性,但并未隐藏所有细节。理解dotnetCLI 命令背后的 MSBuild 目标、掌握项目文件中的关键属性、合理配置热重载与发布选项,能让你从被工具驱动转变为驱动工具。
本文从开发者的实际痛点出发,拆解了从项目创建到生产部署的全流程工具使用与配置。真正的熟练,始于在遇到“构建失败”或“热重载无效”时,你能有条不紊地查看输出日志、检查项目配置、并知道该调整哪个开关。建议你将此文档作为参考,在下一个 Blazor 项目中,有意识地尝试修改<PublishTrimmed>或<RunAOTCompilation>等配置,观察其对输出大小和性能的影响,这种实践带来的理解远比阅读文档更深刻。