注意
這不是這篇文章的最新版本。 關於目前版本,請參閱 本文的 .NET 10 版本。
警告
不再支援此版本的 ASP.NET Core。 如需詳細資訊,請參閱 .NET 和 .NET Core 支持原則。 如需目前的版本,請參閱 本文的 .NET 9 版本。
本文說明如何在建置 Blazor 應用程式時,控制中繼語言 (IL) 修剪器。
Blazor WebAssembly 會執行中繼語言 (IL) 修剪,以減少已發佈輸出的大小。 發佈應用程式時會發生修剪。
預設修剪器粒度
應用程式的 Blazor 預設修剪器粒度是 partial,這表示只會修剪核心架構程式庫和已明確啟用修剪支援的程式庫。 不支援整體修剪功能。
如需詳細資訊,請參閱修剪選項 (.NET 文件)。
組態
若要設定 IL 修剪器,請參閱 .NET 基本概念文件中的修剪選項一文,其中包含下列主題的指引:
- 使用專案檔中的
<PublishTrimmed>屬性,停用整個應用程式的修剪。 - 控制 IL 修剪器積極捨棄未使用 IL 的方式。
- 停止 IL 修剪器修剪特定組件。
- 用於修剪的「根」組件。
- 在專案檔中將
<SuppressTrimAnalysisWarnings>屬性設定為false,以針對反映的類型顯露警告。 - 控制符號精簡和除錯支援。
- 設定 IL 修剪器功能以便修剪架構程式庫功能。
當 修剪器粒度 為 partial時,這是預設值,IL 修剪器會修剪基類程式庫,以及標示為可修剪的任何其他元件。 若要選擇在任何應用程式的類別庫專案中進行修剪,請在這些專案中將 MSBuild 屬性設定 <IsTrimmable> 為 true :
<PropertyGroup>
<IsTrimmable>true</IsTrimmable>
</PropertyGroup>
如需與 .NET 程式庫相關的指引,請參閱 準備 .NET 程式庫以進行修剪。
無法保留已發行應用程式所使用的類型
修剪可能會對已發佈的應用程式產生有害影響,導致執行階段錯誤,即使已將屬性<PublishTrimmed>設定為專案檔中也一樣。 在使用 反映的應用程式中,IL 修剪器通常無法判斷運行時間反映的必要類型,並修剪它們,或從方法修剪參數名稱。 這可能發生於用於 JS 互操作、JSON 序列化/反序列化和其他操作的複雜框架類型。
IL 修剪器也無法在執行階段對應用程式的動態行為做出反應。 為了確保已修剪的應用程式在部署後正常運作,請在開發時經常測試已發佈的輸出。
請考慮下列範例,該範例會執行 JSON 還原序列化為 Tuple<T1,T2> 集合 (List<Tuple<string, string>>)。
TrimExample.razor:
@page "/trim-example"
@using System.Diagnostics.CodeAnalysis
@using System.Text.Json
<h1>Trim Example</h1>
<ul>
@foreach (var item in @items)
{
<li>@item.Item1, @item.Item2</li>
}
</ul>
@code {
private List<Tuple<string, string>> items = [];
[StringSyntax(StringSyntaxAttribute.Json)]
private const string data =
"""[{"item1":"1:T1","item2":"1:T2"},{"item1":"2:T1","item2":"2:T2"}]""";
protected override void OnInitialized()
{
JsonSerializerOptions options = new() { PropertyNameCaseInsensitive = true };
items = JsonSerializer
.Deserialize<List<Tuple<string, string>>>(data, options)!;
}
}
當應用程式在本機執行時,上述元件會正常執行,並產生下列轉譯清單:
• 1:T1、1:T2
• 2:T2、2:T2
發佈應用程式時,會從應用程式中修剪, Tuple<T1,T2> 即使已在專案檔中將屬性設定 <PublishTrimmed> 為 false 也一樣。 存取元件會拋出以下例外狀況:
crit: Microsoft.AspNetCore.Components.WebAssembly.Rendering.WebAssemblyRenderer[100]
Unhandled exception rendering component: ConstructorContainsNullParameterNames, System.Tuple`2[System.String,System.String]
System.NotSupportedException: ConstructorContainsNullParameterNames, System.Tuple`2[System.String,System.String]
若要解決遺失的類型,請考慮採用下列其中一種方法。
自訂類型
若要避免在依賴反射的案例中發生 .NET 修剪問題,例如互操作性和 JSON 序列化,請使用不可修剪程式庫中定義的自訂類型,或透過連結器設定保留這些類型。
下列修改會建立 StringTuple 型別以供元件使用。
StringTuple.cs:
[method: SetsRequiredMembers]
public sealed class StringTuple(string item1, string item2)
{
public required string Item1 { get; init; } = item1;
public required string Item2 { get; init; } = item2;
}
元件會修改為使用 StringTuple 類型:
- private List<Tuple<string, string>> items = [];
+ private List<StringTuple> items = [];
- items = JsonSerializer.Deserialize<List<Tuple<string, string>>>(data, options)!;
+ items = JsonSerializer.Deserialize<List<StringTuple>>(data, options)!;
因為在發佈應用程式時,不會修剪不可修剪元件中定義的 Blazor 自訂類型,所以元件會在發佈應用程式之後依設計運作。
如果您偏好使用架構類型,儘管有我們的建議,請使用下列任一方法:
如果您不顧我們的建議而偏好使用架構類型,請 將類型保留為動態相依性。
將類型保留為動態相依性
建立動態相依性,以保留具有屬性的[DynamicDependency]類型。
如果還不存在,請新增 @using 的 System.Diagnostics.CodeAnalysis指示詞:
@using System.Diagnostics.CodeAnalysis
新增[DynamicDependency]屬性以保留Tuple<T1,T2>:
+ [DynamicDependency(DynamicallyAccessedMemberTypes.PublicConstructors,
+ typeof(Tuple<string, string>))]
private List<Tuple<string, string>> items = [];
使用根描述元
根描述元可以保留類型。
將檔案新增至 ILLink.Descriptors.xml 應用程式的根目錄†類型為:
<linker>
<assembly fullname="System.Private.CoreLib">
<type fullname="System.Tuple`2" preserve="all" />
</assembly>
</linker>
†應用程式的根是指應用程式的 Blazor WebAssembly 根目錄或專案的 .ClientBlazor Web App 根目錄(.NET 8 或更新版本)。
將項目 TrimmerRootDescriptor 新增至應用程式的專案檔案‡,並參考該 ILLink.Descriptors.xml 檔案:
<ItemGroup>
<TrimmerRootDescriptor Include="$(MSBuildThisFileDirectory)ILLink.Descriptors.xml" />
</ItemGroup>
‡專案檔是應用程式的Blazor WebAssembly專案檔,或是 (.NET 8 或更新版本) 專案.Client的Blazor Web App專案檔。
.NET 8 中的因應措施
作為 .NET 8 中的因應措施,您可以在應用程式的專案檔中新增 _ExtraTrimmerArgs MSBuild 屬性 --keep-metadata parametername ,以在修剪期間保留參數名稱:
<PropertyGroup>
<_ExtraTrimmerArgs>--keep-metadata parametername</_ExtraTrimmerArgs>
</PropertyGroup>