Nota
O acesso a esta página requer autorização. Podes tentar iniciar sessão ou mudar de diretório.
O acesso a esta página requer autorização. Podes tentar mudar de diretório.
Observação
Esta não é a versão mais recente deste artigo. Para a versão atual, consulte a versão .NET 10 deste artigo.
Advertência
Esta versão do ASP.NET Core não é mais suportada. Para obter mais informações, consulte a Política de suporte do .NET e .NET Core. Para a versão atual, consulte a versão .NET 10 deste artigo.
Este artigo explica como controlar o Intermediate Language (IL) Trimmer ao criar um Blazor aplicativo.
Blazor WebAssembly executa o corte de linguagem intermediária (IL) para reduzir o tamanho da saída publicada. O corte ocorre ao publicar um aplicativo.
Granularidade padrão do trimmer
A granularidade padrão do trimmer para Blazor aplicativos é partial, o que significa que apenas as bibliotecas da estrutura principal e as bibliotecas que habilitaram explicitamente o suporte à filtragem são cortadas. O corte total não é suportado.
Para obter mais informações, consulte Opções de corte (documentação do .NET).
Configuração
Para configurar o IL Trimmer, consulte o artigo Opções de corte na documentação do .NET Fundamentals, que inclui orientações sobre os seguintes assuntos:
- Desative a eliminação para toda a aplicação com a propriedade
<PublishTrimmed>no ficheiro de projeto. - Controle quão agressivamente a IL não utilizada é eliminada pelo IL Trimmer.
- Impeça o IL Trimmer de cortar montagens específicas.
- Montagens "raiz" para corte.
- Exiba avisos para tipos de dados refletidos configurando a propriedade
<SuppressTrimAnalysisWarnings>parafalseno ficheiro do projeto. - Controle a remoção de símbolos e o suporte para depuração.
- Defina os recursos do IL Trimmer para cortar os recursos da biblioteca da estrutura.
Quando a granularidade do trimmer é partial, que é o valor padrão, o IL Trimmer corta a biblioteca de classes base e quaisquer outros assemblies marcados como trimmable. Para optar por cortar em qualquer um dos projetos de biblioteca de classes do aplicativo, defina a <IsTrimmable> propriedade MSBuild como true nesses projetos:
<PropertyGroup>
<IsTrimmable>true</IsTrimmable>
</PropertyGroup>
Para obter orientações relacionadas às bibliotecas .NET, consulte Preparar bibliotecas .NET para corte.
Falha ao preservar os tipos usados por um aplicativo publicado
O corte pode ter efeitos prejudiciais para um aplicativo publicado, levando a erros de tempo de execução, mesmo apesar de definir a <PublishTrimmed> propriedade como false no arquivo de projeto. Em aplicações que usam reflexão, o IL Trimmer muitas vezes não consegue determinar os tipos necessários para reflexão em tempo de execução e remove-os ou remove os nomes dos parâmetros dos métodos. Isso pode acontecer com tipos de frameworks complexos usados para JS interoperabilidade, serialização/desserialização JSON e para outras operações.
O IL Trimmer também não consegue reagir ao comportamento dinâmico de um aplicativo em tempo de execução. Para garantir que o aplicativo cortado funcione corretamente depois de implantado, teste a saída publicada com frequência durante o desenvolvimento.
Considere o exemplo a seguir que executa a desserialização JSON em uma Tuple<T1,T2> coleção (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)!;
}
}
O componente anterior é executado normalmente quando o aplicativo é executado localmente e produz a seguinte lista renderizada:
• 1:T1, 1:T2
• 2:T2, 2:T2
Quando o aplicativo é publicado, Tuple<T1,T2> é cortado do aplicativo, mesmo apesar de definir a <PublishTrimmed> propriedade como false no arquivo de projeto. O acesso ao componente gera a seguinte exceção:
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]
Para lidar com tipos perdidos, considere adotar uma das seguintes abordagens.
Tipos personalizados
Para evitar problemas com a eliminação do .NET em cenários que dependem de reflexão de código, como interoperabilidade e serialização JSON, use tipos personalizados definidos em bibliotecas não elimináveis ou preserve os tipos por meio de configuração do linker.
As modificações a seguir criam um StringTuple tipo para uso pelo componente.
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;
}
O componente é modificado para usar o StringTuple tipo:
- 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)!;
Como os tipos personalizados definidos em assemblies não removíveis não são eliminados por Blazor durante a publicação de um aplicativo, o componente funciona conforme projetado após a publicação do aplicativo.
Se você preferir usar tipos de estrutura apesar de nossa recomendação, use uma das seguintes abordagens:
Se você preferir usar tipos de estrutura apesar de nossa recomendação, preserve o tipo como uma dependência dinâmica.
Preservar o tipo como uma dependência dinâmica
Crie uma dependência dinâmica para preservar o tipo com o [DynamicDependency] atributo.
Se ainda não estiver presente, adicionar a @using diretiva para System.Diagnostics.CodeAnalysis.
@using System.Diagnostics.CodeAnalysis
Adicione um [DynamicDependency] atributo para preservar o Tuple<T1,T2>:
+ [DynamicDependency(DynamicallyAccessedMemberTypes.PublicConstructors,
+ typeof(Tuple<string, string>))]
private List<Tuple<string, string>> items = [];
Usar um descritor raiz
Um descritor raiz pode preservar o tipo.
Adicione um ILLink.Descriptors.xml arquivo à raiz do aplicativo† com o tipo:
<linker>
<assembly fullname="System.Private.CoreLib">
<type fullname="System.Tuple`2" preserve="all" />
</assembly>
</linker>
†A raiz do aplicativo refere-se à raiz do Blazor WebAssembly aplicativo ou à .Client raiz do projeto de um Blazor Web App (.NET 8 ou posterior).
Adicione um TrimmerRootDescriptor item ao arquivo de projeto do aplicativo‡ fazendo referência ao ILLink.Descriptors.xml arquivo:
<ItemGroup>
<TrimmerRootDescriptor Include="$(MSBuildThisFileDirectory)ILLink.Descriptors.xml" />
</ItemGroup>
‡O arquivo de projeto é o arquivo de projeto do Blazor WebAssembly aplicativo ou o arquivo de projeto do .Client projeto de um Blazor Web App (.NET 8 ou posterior).
Solução alternativa no .NET 8
Como uma solução alternativa no .NET 8, você pode adicionar a _ExtraTrimmerArgs propriedade MSBuild definida como --keep-metadata parametername no arquivo de projeto do aplicativo para preservar nomes de parâmetros durante o corte:
<PropertyGroup>
<_ExtraTrimmerArgs>--keep-metadata parametername</_ExtraTrimmerArgs>
</PropertyGroup>