1. 背景我在做一个 WinUI3 项目AotNativeWinui3最初是按“全自包含 AOT 裁剪”去发版。直觉上应该很小但实际发布目录文件很多体积也不理想。后面我对照做了几轮实测最终得到一套更稳定、可解释的参数组合。注意事项一定要看WindowsAppSDKSelfContainedfalse前提是目标机有环境。裁剪后必须做核心路径回归尤其反射/动态访问相关。AOT 发布建议至少保留一套“带符号”的构建命令方便问题定位。F5 开发调试正常可用验证发布产物建议“先 publish 再附加调试”。DisableRuntimeMarshalling不建议为“追体积”而开启它主要影响互操作行为和稳定性不是体积优化主开关。2. 一句话先说结论AOT 的优势确实很大特别是启动速度。但“体积大头”常常不是 IL而是运行时和本机依赖WinAppSDK、WebView2、ONNX、DirectML 等。如果目标机器已经有运行环境WebView2 Windows App Runtime可以用“小包 AOT”策略SelfContainedtruePublishAottruePublishTrimmedtrueWindowsAppSDKSelfContainedfalse我这边实测 Release 可做到约6.2 MB6 个文件。3. 我踩过的关键点3.1 AOT 不是万能“压缩器”AOT 的核心是“预编译 IL 到本机代码”它主要改善启动和运行时行为。它不会自动把所有外部本机依赖都消掉。3.2 裁剪只裁托管可分析代码PublishTrimmedtrue主要针对托管代码路径。对于 WinUI3 / WinAppSDK / WebView2 这类本机依赖裁剪帮助有限。3.3 体积真正分水岭是否自带运行时WindowsAppSDKSelfContained这个参数影响非常大。true更独立但目录会明显变大。false目录变小但要求目标机有对应运行时。4. 参数说明4.1PublishAot含义启用 Native AOT。价值启动更快、内存曲线更稳定通常也能减少主程序体积。风险对动态代码、反射场景更敏感。4.2SelfContained含义是否把 .NET 运行时打进产物。在 AOT 场景里通常需要true。4.3PublishTrimmed含义开启裁剪。价值减少托管代码体积。注意可能误裁需要关注 trim 警告并做回归验证。4.4PublishSingleFile含义尝试单文件发布。WinUI3 场景通常不作为首选容易引入兼容性和排查成本。4.5WindowsAppSDKSelfContained含义是否把 WinAppSDK runtime 一并放进发布目录。这是 WinUI3 项目里影响体积最明显的参数之一。4.6DebugType/DebugSymbols含义控制 PDB。发版可关调试可开。开启后可调试但 PDB 体积会变大这是正常现象。4.7DisableRuntimeMarshalling含义关闭运行时默认封送Runtime Marshalling。背景.NET 在托管与非托管边界调用时会做字符串、数组、结构体等类型的自动封送关闭后很多自动行为会被禁用需要你显式处理互操作细节。价值在高频互操作场景下可能降低封送开销、提升可预测性也更贴近 AOT 的“显式控制”思路。风险对现有 P/Invoke / COM 互操作兼容性影响较大迁移成本高容易引入隐蔽问题。实战建议像本文这个 WinUI3 WebView2 工程优先保持false先追求稳定性。只有在你明确识别到互操作成为瓶颈、并且具备完整互操作测试覆盖时再评估切到true。5. 我们最终采用的发布策略5.1 策略目标保留 AOT 性能优势把发布目录做小用安装环境兜底运行时。5.2 对应配置SmallAotPublishPropertyGroup Condition$(SmallAotPublish) true SelfContainedtrue/SelfContained PublishAottrue/PublishAot PublishTrimmedtrue/PublishTrimmed PublishSingleFilefalse/PublishSingleFile DisableRuntimeMarshallingfalse/DisableRuntimeMarshalling WindowsAppSDKSelfContainedfalse/WindowsAppSDKSelfContained /PropertyGroup5.3 发布命令dotnet publish D:\Codes\NativeAOT\NativeAOT\AotNativeWinui3\AotNativeWinui3.csproj -c Release -r win-x64 -p:SmallAotPublishtrue6. 实测数据6.1 小包 AOTRelease命令-p:SmallAotPublishtrue结果Files6, TotalMB6.2典型文件AotNativeWinui3.exeMicrosoft.Web.WebView2.Core.dllMicrosoft.WindowsAppRuntime.Bootstrap.dllWebView2Loader.dllAotNativeWinui3.pri7. Debug 和 Release 到底差在哪即便你不显式写DebugType/DebugSymbols-c Debug和-c Release依然不同优化级别不同Release 更偏性能与体积条件编译常量不同如DEBUG调试体验不同Debug 更友好AOT 下最终可观测体积和行为仍建议以 Release 为准9. 最终推荐命令清单9.1 发版小包默认dotnet publish D:\Codes\NativeAOT\NativeAOT\AotNativeWinui3\AotNativeWinui3.csproj -c Release -r win-x64 -p:SmallAotPublishtrue9.2 发版小包带 PDBdotnet publish D:\Codes\NativeAOT\NativeAOT\AotNativeWinui3\AotNativeWinui3.csproj -c Release -r win-x64 -p:SmallAotPublishtrue -p:DebugTypeportable -p:DebugSymbolstrue9.3 开发验证Debugdotnet publish D:\Codes\NativeAOT\NativeAOT\AotNativeWinui3\AotNativeWinui3.csproj -c Debug -r win-x64 -p:SmallAotPublishtrue10. 结语这次实践让我更确定一件事WinUI3 AOT 的优化不是“开一个参数就结束”而是一个组合策略AOT 决定性能基线