Nota:
El acceso a esta página requiere autorización. Puede intentar iniciar sesión o cambiar directorios.
El acceso a esta página requiere autorización. Puede intentar cambiar los directorios.
Nota
Esta no es la versión más reciente de este artículo. Para la versión actual, consulte la versión de .NET 9 de este artículo.
Advertencia
Esta versión de ASP.NET Core ya no se admite. Para obtener más información, consulte la directiva de compatibilidad de .NET y .NET Core. Para la versión actual, consulte la versión de .NET 9 de este artículo.
Importante
Esta información hace referencia a un producto en versión preliminar, el cual puede sufrir importantes modificaciones antes de que se publique la versión comercial. Microsoft no proporciona ninguna garantía, expresa o implícita, con respecto a la información proporcionada aquí.
Para la versión actual, consulte la versión de .NET 9 de este artículo.
En este artículo se explica cómo controlar el recortador de lenguaje intermedio al compilar una aplicación Blazor.
Blazor WebAssembly realiza un recorte de lenguaje intermedio (IL) para reducir el tamaño de la salida publicada. El recorte se produce cuando se publica la aplicación.
Granularidad del recortador predeterminada
La granularidad del optimizador predeterminada para Blazor las aplicaciones es partial, lo que significa que solo se recortan las bibliotecas principales del marco y las bibliotecas que han habilitado explícitamente la compatibilidad con trimming. No se admite el recorte completo.
Para obtener más información, consulta Opciones de recorte (documentación de .NET).
Configuración
Para configurar el recortador de IL, consulta el artículo Opciones de recorte en la documentación sobre aspectos básicos de .NET, que incluye instrucciones sobre los temas siguientes:
- Deshabilitación del recorte para toda la aplicación con la propiedad
<PublishTrimmed>en el archivo de proyecto - Control de la agresividad con la que el recortador de IL descarta el IL sin usar.
- Interrupción del recorte de ensamblados específicos por parte del recortador de IL.
- Ensamblados "raíz" para recortar
- Obtención de advertencias para los tipos reflejados mediante el establecimiento de la propiedad
<SuppressTrimAnalysisWarnings>enfalseen el archivo de proyecto - Control del recorte de símbolos y compatibilidad con el depurador.
- Establecimiento de características de recortador de IL para las características de la biblioteca de marcos de recorte.
Cuando la granularidad del optimizador es partial, que es el valor predeterminado, el Recortador IL recorta la biblioteca de clases base y cualquier otro ensamblado marcado como recortable. Para habilitar la depuración en cualquiera de los proyectos de biblioteca de clases de la aplicación, establezca la propiedad MSBuild <IsTrimmable> a true en esos proyectos.
<PropertyGroup>
<IsTrimmable>true</IsTrimmable>
</PropertyGroup>
Para obtener instrucciones relativas a las bibliotecas de .NET, consulte Preparación de bibliotecas de .NET para el recorte.
Error al conservar los tipos usados por una aplicación publicada
El recorte puede tener efectos perjudiciales para una aplicación publicada que conduce a errores en tiempo de ejecución, incluso a pesar de establecer la <PublishTrimmed> propiedadfalse en en el archivo del proyecto. En las aplicaciones que usan reflexión, el optimizador de IL a menudo no puede determinar los tipos necesarios para la reflexión en tiempo de ejecución y los recorta o recorta los nombres de parámetro de los métodos. Esto puede ocurrir con tipos de marcos complejos que se usan para JS la interoperabilidad, la serialización y deserialización JSON y otras operaciones.
El recortador de IL tampoco puede reaccionar a un comportamiento dinámico de la aplicación en runtime. Para asegurarte de que la aplicación recortada funciona correctamente una vez implementada, prueba la salida publicada con frecuencia durante el desarrollo.
Considere el ejemplo siguiente que realiza la deserialización JSON en una Tuple<T1,T2> colección (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)!;
}
}
El componente anterior se ejecuta normalmente cuando la aplicación se ejecuta localmente y genera la siguiente lista representada:
• 1:T1, 1:T2
• 2:T2, 2:T2
Cuando se publica la aplicación, Tuple<T1,T2> se recorta de la aplicación, incluso a pesar de establecer la <PublishTrimmed> propiedad false en en el archivo del proyecto. El acceso al componente produce la siguiente excepción:
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 abordar los tipos perdidos, considere la posibilidad de adoptar uno de los métodos siguientes.
Tipos personalizados
Para evitar problemas con el recorte de .NET en escenarios que dependen de la reflexión, como JS la interoperabilidad y la serialización JSON, use tipos personalizados definidos en bibliotecas no recortables o conserve los tipos a través de la configuración del vinculador.
Las modificaciones siguientes crean un StringTuple tipo para su uso por parte del 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;
}
El componente se modifica para usar el 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)!;
Dado que los tipos personalizados definidos en ensamblados no recortables no se recortan Blazor cuando se publica una aplicación, el componente funciona según lo diseñado después de publicar la aplicación.
Si prefiere usar tipos de marco a pesar de nuestra recomendación, use cualquiera de los enfoques siguientes:
Si prefiere usar tipos de marco a pesar de nuestra recomendación, conserve el tipo como una dependencia dinámica.
Mantener el tipo como una dependencia dinámica
Cree una dependencia dinámica para conservar el tipo con el [DynamicDependency] atributo .
Si aún no está presente, agregue una @using directiva para System.Diagnostics.CodeAnalysis:
@using System.Diagnostics.CodeAnalysis
Agregue un [DynamicDependency] atributo para conservar el Tuple<T1,T2>.
+ [DynamicDependency(DynamicallyAccessedMemberTypes.PublicConstructors,
+ typeof(Tuple<string, string>))]
private List<Tuple<string, string>> items = [];
Usar un descriptor raíz
Un descriptor raíz puede conservar el tipo.
Agregue un ILLink.Descriptors.xml archivo a la raíz de la aplicación† con el tipo :
<linker>
<assembly fullname="System.Private.CoreLib">
<type fullname="System.Tuple`2" preserve="all" />
</assembly>
</linker>
†La raíz de la aplicación hace referencia a la raíz de la Blazor WebAssembly aplicación o a la .Client raíz del proyecto de Blazor Web App (.NET 8 o posterior).
Agregue un TrimmerRootDescriptor elemento al archivo de proyecto de la aplicación y haga referencia al ILLink.Descriptors.xml archivo:
<ItemGroup>
<TrimmerRootDescriptor Include="$(MSBuildThisFileDirectory)ILLink.Descriptors.xml" />
</ItemGroup>
El archivo de proyecto es el archivo de proyecto de la Blazor WebAssembly aplicación o el archivo de proyecto del .Client proyecto de ( Blazor Web App .NET 8 o posterior).
Solución alternativa en .NET 8
Como solución alternativa en .NET 8, puede agregar la _ExtraTrimmerArgs propiedad MSBuild establecida --keep-metadata parametername en el archivo de proyecto de la aplicación para conservar los nombres de parámetro durante el recorte:
<PropertyGroup>
<_ExtraTrimmerArgs>--keep-metadata parametername</_ExtraTrimmerArgs>
</PropertyGroup>