Observação
O acesso a essa página exige autorização. Você pode tentar entrar ou alterar diretórios.
O acesso a essa página exige autorização. Você pode tentar alterar os diretórios.
Observação
Esta não é a versão mais recente deste artigo. Para a versão atual, consulte a versão do .NET 10 deste artigo.
Aviso
Esta versão do ASP.NET Core não tem mais suporte. Para obter mais informações, consulte a Política de Suporte do .NET e do .NET Core. Para a versão atual, consulte a versão do .NET 10 deste artigo.
Este artigo explica como controlar o Filtro de Linguagem Intermediária (IL) ao criar um aplicativo Blazor.
O Blazor WebAssembly executa o corte do IL (linguagem intermediária) para reduzir o tamanho da saída publicada. O corte ocorre ao publicar um aplicativo.
Granularidade padrão do filtro
A granularidade padrão do aparador para Blazor aplicativos é partial, o que significa que apenas as bibliotecas e bibliotecas de estrutura principal que habilitaram explicitamente o suporte de corte são cortadas. Não há suporte para corte completo.
Para obter mais informações, confira Opções de corte (documentação do .NET).
Configuração
Para configurar o IL Trimmer, confira o artigo Opções de corte na documentação de Conceitos básicos do .NET, que inclui diretrizes sobre os seguintes assuntos:
- Desabilitar o corte do aplicativo inteiro com a propriedade
<PublishTrimmed>no arquivo de projeto. - Controlar o nível de agressividade do descarte da IL não utilizada pelo IL Trimmer.
- Impedir que o IL Trimmer corte assemblies específicos.
- Assemblies "raiz" para corte.
- Avisos do Surface para tipos refletidos ao definir a propriedade
<SuppressTrimAnalysisWarnings>comofalseno arquivo de projeto. - Controlar o corte de símbolos e o suporte ao depurador.
- Definir os recursos do IL Trimmer para cortar recursos da biblioteca de estruturas.
Quando a granularidade do aparador é partial, que é o valor padrão, o IL Trimmer elimina a biblioteca de classes base e quaisquer outros assemblies marcados como removíveis. Para optar pelo corte em qualquer um dos projetos de biblioteca de classes do aplicativo, defina a propriedade MSBuild nesses projetos para <IsTrimmable>:
<PropertyGroup>
<IsTrimmable>true</IsTrimmable>
</PropertyGroup>
Para obter diretrizes relacionadas às bibliotecas do .NET, consulte Preparar bibliotecas do .NET para trimming.
Falha ao preservar os tipos usados por um aplicativo publicado
O corte pode ter efeitos prejudiciais para um aplicativo publicado que leva a erros de runtime, mesmo que a <PublishTrimmed> propriedadefalse seja definida no arquivo de projeto. Em aplicativos 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 os remove, ou remove os nomes dos parâmetros dos métodos. Isso pode acontecer com tipos de estrutura complexos usados para interoperabilidade JS, serialização/desserialização JSON e outras operações.
O IL Trimmer também não consegue reagir ao comportamento dinâmico de um aplicativo em runtime. 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 que a <PublishTrimmed> propriedade false seja configurada no arquivo de projeto. Acessar o 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 a adoção de uma das abordagens a seguir.
Tipos personalizados
Para evitar problemas com a redução do .NET em cenários que dependem de reflection, como interoperabilidade e serialização JSON, use tipos personalizados definidos em bibliotecas configuradas para não serem reduzidas ou preserve os tipos por meio da configuração do vinculador.
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-trimmáveis não são aparados por Blazor quando um aplicativo é publicado, o componente opera como 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, adicione uma @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 à raiz do .Client projeto de um Blazor Web App (.NET 8 ou posterior).
Adicione um TrimmerRootDescriptor item ao arquivo de projeto do aplicativo‡ referenciando o 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 propriedade MSBuild definida _ExtraTrimmerArgs no arquivo de projeto do aplicativo para preservar nomes de parâmetro durante o --keep-metadata parametername corte:
<PropertyGroup>
<_ExtraTrimmerArgs>--keep-metadata parametername</_ExtraTrimmerArgs>
</PropertyGroup>