Compartir a través de


Archivos estáticos Blazor en ASP.NET Core

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, consulta la Directiva de soporte técnico de .NET y .NET Core. Para la versión actual, consulta la versión .NET 8 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 describe la configuración de la aplicación Blazor para servir archivos estáticos.

Entrega de recursos estáticos en aplicaciones del lado Blazor servidor

El servicio de recursos estáticos se administra mediante convenciones de punto de conexión de enrutamiento o un middleware descrito en la tabla siguiente.

Característica API Versión de .NET Descripción
Asignación de convenciones de punto de conexión de enrutamiento de recursos estáticos MapStaticAssets .NET 9 o posterior Optimiza la entrega de recursos estáticos a los clientes.
Middleware de archivos estáticos UseStaticFiles Todas las versiones de .NET Proporciona recursos estáticos a los clientes sin las optimizaciones de los recursos estáticos de asignación, pero útiles para algunas tareas que asignan recursos estáticos no son capaces de administrar.

Configure Map Static Assets mediante una llamada a MapStaticAssets en la canalización de procesamiento de solicitudes de la aplicación, que realiza lo siguiente:

Map Static Assets funciona combinando procesos de compilación y publicación para recopilar información sobre los recursos estáticos de la aplicación. La biblioteca en runtime utiliza esta información para servir eficazmente los recursos estáticos a los exploradores.

Asignar activos estáticos puede reemplazar UseStaticFiles en la mayoría de las situaciones. Sin embargo, los recursos estáticos de asignación están optimizados para atender los recursos desde ubicaciones conocidas de la aplicación en tiempo de compilación y publicación. Si la aplicación atiende recursos de otras ubicaciones, como el disco o los recursos incrustados, debe usarse UseStaticFiles.

Map Static Assets (MapStaticAssets) reemplaza la llamada UseBlazorFrameworkFiles a en aplicaciones que atienden Blazor WebAssembly archivos de marco y no es necesario llamar UseBlazorFrameworkFiles explícitamente a en porque Blazor Web App se llama automáticamente a la API al invocar AddInteractiveWebAssemblyComponents.

Asignar recursos estáticos proporciona las siguientes ventajas que no están disponibles al llamar a UseStaticFiles:

  • Compresión durante la compilación de todos los activos de la aplicación, incluidos JavaScript (JS) y las hojas de estilo, pero excluyendo los activos de imágenes y fuentes que ya están comprimidos. Durante el desarrollo se utiliza la compresión Gzip (Content-Encoding: gz). Durante la publicación se utiliza la compresión Gzip con Brotli (Content-Encoding: br).
  • Huella digital para todos los activos en runtime con una cadena codificada en Base64 del hash SHA-256 del contenido de cada archivo. De este modo, se evita reutilizar una versión antigua de un archivo, aunque el archivo antiguo esté almacenado en caché. Los activos con huella digital se almacenan en caché mediante la immutable directiva, lo que hace que el navegador no vuelva a solicitar el activo hasta que cambie. Para los navegadores que no soportan la directiva immutable, se agrega una max-age directiva.
    • Incluso si un activo no tiene huella digital, un contenido basado ETags se genera para cada activo estático utilizando el hash de la huella digital del archivo como valor ETag. Esto garantiza que el navegador solo descargue un archivo si su contenido cambia (o si el archivo se descarga por primera vez).
    • Internamente, Blazor asigna los activos físicos a sus huellas dactilares, lo que permite a la aplicación:
      • Busque activos Blazor generados automáticamente, como CSS con ámbito de componente Razor para la función Blazor de aislamiento de CSS de y JS activos descritos por JS mapas de importación.
      • Generar etiquetas de vínculo en el contenido <head> de la página para precargar activos.
  • Durante las pruebas de desarrollo de Recarga activa de Visual Studio:
    • La información de integridad se elimina de los activos para evitar problemas cuando se modifica un archivo mientras se ejecuta la aplicación.
    • Los activos estáticos no se almacenan en caché para garantizar que el navegador siempre recupere el contenido actual.

Cuando están habilitados los modos WebAssembly Interactivo o Auto renderizado Interactivo:

  • Blazor crea un punto de conexión para exponer la colección de recursos como un módulo JS.
  • La URL se emite en el cuerpo de la solicitud como estado persistente del componente cuando un componente WebAssembly se renderiza en la página.
  • Durante el arranque de WebAssembly, Blazor recupera la URL, importa el módulo y llama a una función para recuperar la colección de activos y reconstruirla en memoria. La URL es específica del contenido y se almacena en caché para siempre, por lo que este coste general solo se paga una vez por usuario hasta que se actualiza la aplicación.
  • La colección de recursos también se expone en una URL legible por humanos (_framework/resource-collection.js), por lo que JS tiene acceso a la colección de recursos para mejorar la navegación o para implementar características de otros frameworks y componentes de terceros.

Los recursos estáticos de asignación no proporcionan características para la minificación u otras transformaciones de archivo. La minificación suele realizarse mediante código personalizado o herramientas de terceros.

El middleware de archivos estáticos (UseStaticFiles) es útil en las siguientes situaciones que no pueden controlar los recursos estáticos de asignación (MapStaticAssets):

Para obtener más información, vea Archivos estáticos en ASP.NET Core.

Entrega de recursos con convenciones de punto de conexión de enrutamiento de recursos estáticos de asignación

Esta sección se aplica a las aplicaciones Blazor del lado del servidor.

Los recursos se entregan a través de la ComponentBase.Assets propiedad , que resuelve la dirección URL con huella digital de un recurso determinado. En el ejemplo siguiente, Bootstrap, la Blazor hoja de estilos de la aplicación de plantilla de proyecto (app.css) y la hoja de estilos de aislamiento css (basada en el espacio de nombres de una aplicación de BlazorSample) están vinculadas en un componente raíz, normalmente el App componente (Components/App.razor):

<link rel="stylesheet" href="@Assets["bootstrap/bootstrap.min.css"]" />
<link rel="stylesheet" href="@Assets["app.css"]" />
<link rel="stylesheet" href="@Assets["BlazorSample.styles.css"]" />

Importación de mapas

Esta sección se aplica a las aplicaciones Blazor del lado del servidor.

El componente Importar mapa (ImportMap) representa un elemento de mapa de importación (<script type="importmap"></script>) que define el mapa de importación para los scripts de módulo. El componente Importar mapa se coloca en <head> el contenido del componente raíz, normalmente el App componente (Components/App.razor).

<ImportMap />

Si no se asigna un elemento personalizado ImportMapDefinition a un componente importar mapa, el mapa de importación se genera en función de los recursos de la aplicación.

Los siguientes ejemplos muestran definiciones de asignación de importación personalizadas y las asignaciones de importación que crean.

Asignación básica de importación:

new ImportMapDefinition(
    new Dictionary<string, string>
    {
        { "jquery", "https://cdn.example.com/jquery.js" },
    },
    null,
    null);

El código anterior da como resultado la siguiente asignación de importación:

{
  "imports": {
    "jquery": "https://cdn.example.com/jquery.js"
  }
}

Asignación básica de ámbito:

new ImportMapDefinition(
    null,
    new Dictionary<string, IReadOnlyDictionary<string, string>>
    {
        ["/scoped/"] = new Dictionary<string, string>
        {
            { "jquery", "https://cdn.example.com/jquery.js" },
        }
    },
    null);

El código anterior da como resultado la siguiente asignación de importación:

{
  "scopes": {
    "/scoped/": {
      "jquery": "https://cdn.example.com/jquery.js"
    }
  }
}

Importación de asignación con integridad:

new ImportMapDefinition(
    new Dictionary<string, string>
    {
        { "jquery", "https://cdn.example.com/jquery.js" },
    },
    null,
    new Dictionary<string, string>
    {
        { "https://cdn.example.com/jquery.js", "sha384-abc123" },
    });

El código anterior da como resultado la siguiente asignación de importación:

{
  "imports": {
    "jquery": "https://cdn.example.com/jquery.js"
  },
  "integrity": {
    "https://cdn.example.com/jquery.js": "sha384-abc123"
  }
}

Combinar definiciones de asignación de importación (ImportMapDefinition) con ImportMapDefinition.Combine.

Asignación de importación creada a partir de un ResourceAssetCollection que asigna activos estáticos a sus correspondientes URL únicas:

ImportMapDefinition.FromResourceCollection(
    new ResourceAssetCollection(
    [
        new ResourceAsset(
            "jquery.fingerprint.js",
            [
                new ResourceAssetProperty("integrity", "sha384-abc123"),
                new ResourceAssetProperty("label", "jquery.js"),
            ])
    ]));

El código anterior da como resultado la siguiente asignación de importación:

{
  "imports": {
    "./jquery.js": "./jquery.fingerprint.js"
  },
  "integrity": {
    "jquery.fingerprint.js": "sha384-abc123"
  }
}

Configure el middleware de archivos estáticos para servir recursos estáticos a los clientes mediante una llamada a UseStaticFiles en la canalización de procesamiento de solicitudes de la aplicación. Para obtener más información, vea Archivos estáticos en ASP.NET Core.

En versiones anteriores a .NET 8, los archivos estáticos del marco Blazor, como el script de Blazor, se sirven mediante el middleware de archivos estáticos. En .NET 8 o versiones posteriores, los archivos estáticos del marco Blazor se asignan mediante el enrutamiento de puntos de conexión y ya no se usa middleware de archivos estáticos.

Esta sección se aplica a todas las versiones Blazor y aplicaciones .NET.

En las tablas siguientes se resumen los formatos de archivos estáticos <link> href por versión de .NET.

Para conocer la ubicación del contenido <head> donde se colocan los enlaces a archivos estáticos, consulte Estructura del proyecto ASP.NET Core Blazor. Los vínculos de activos estáticos también pueden suministrarse utilizando <HeadContent> componentes en componentes Razor individuales.

Para conocer la ubicación del contenido <head> donde se colocan los enlaces a archivos estáticos, consulte Estructura del proyecto ASP.NET Core Blazor.

.NET 9 o posterior

Tipo de aplicación Valor de href Ejemplos
Blazor Web App @Assets["{PATH}"] <link rel="stylesheet" href="@Assets["app.css"]" />
<link href="@Assets["_content/ComponentLib/styles.css"]" rel="stylesheet" />
Blazor Server† @Assets["{PATH}"] <link href="@Assets["css/site.css"]" rel="stylesheet" />
<link href="@Assets["_content/ComponentLib/styles.css"]" rel="stylesheet" />
Independiente Blazor WebAssembly {PATH} <link rel="stylesheet" href="css/app.css" />
<link href="_content/ComponentLib/styles.css" rel="stylesheet" />

.NET 8.x

Tipo de aplicación Valor de href Ejemplos
Blazor Web App {PATH} <link rel="stylesheet" href="app.css" />
<link href="_content/ComponentLib/styles.css" rel="stylesheet" />
Blazor Server† {PATH} <link href="css/site.css" rel="stylesheet" />
<link href="_content/ComponentLib/styles.css" rel="stylesheet" />
Independiente Blazor WebAssembly {PATH} <link rel="stylesheet" href="css/app.css" />
<link href="_content/ComponentLib/styles.css" rel="stylesheet" />

.NET 7.x o versiones anteriores

Tipo de aplicación Valor de href Ejemplos
Blazor Server† {PATH} <link href="css/site.css" rel="stylesheet" />
<link href="_content/ComponentLib/styles.css" rel="stylesheet" />
Hospedado Blazor WebAssembly‡ {PATH} <link href="css/app.css" rel="stylesheet" />
<link href="_content/ComponentLib/styles.css" rel="stylesheet" />
Blazor WebAssembly {PATH} <link href="css/app.css" rel="stylesheet" />
<link href="_content/ComponentLib/styles.css" rel="stylesheet" />

†Blazor Server es compatible con .NET 8 o posterior, pero ya no es una plantilla de proyecto después de .NET 7.
‡Recomendamos actualizar las aplicaciones Blazor WebAssembly hospedadas a Blazor Web App cuando se adopte .NET 8 o una versión posterior.

Modo de proyecto de activos web estáticos

Esta sección se aplica al proyecto .Client de una Blazor Web App.

La configuración <StaticWebAssetProjectMode>Default</StaticWebAssetProjectMode> necesaria en el proyecto .Client de una Blazor Web App revierte los comportamientos de recursos estáticos de Blazor WebAssembly a los valores predeterminados, de modo que el proyecto se comporte como parte del proyecto hospedado. El SDK Blazor WebAssembly (Microsoft.NET.Sdk.BlazorWebAssembly) configura los recursos web estáticos de una manera específica de trabajar en modo "independiente" con un servidor que simplemente consume las salidas de la biblioteca. Esto no es adecuado para un objeto Blazor Web App, donde la parte WebAssembly de la aplicación es una parte lógica del host y debe comportarse más como una biblioteca. Por ejemplo, el proyecto no expone el conjunto de estilos (por ejemplo, BlazorSample.Client.styles.css) y, en su lugar, solo proporciona el host con el lote de proyectos, para que el host pueda incluirlo en su propio conjunto de estilos.

Cambiar el valor (Default) de <StaticWebAssetProjectMode> o quitar la propiedad del proyecto .Client no se admite.

Archivos estáticos en entornos que no son de Development

Esta sección se aplica a los archivos estáticos del lado servidor.

Cuando se ejecuta una aplicación localmente, los recursos web estáticos solo están habilitados en el entorno de Development. Para habilitar los archivos estáticos para los entornos distintos de Development durante el desarrollo y las pruebas locales (por ejemplo, Staging), llama a UseStaticWebAssets en el WebApplicationBuilder del archivo Program.

Advertencia

Llama UseStaticWebAssets al entorno exacto para evitar la activación de la característica en producción, ya que sirve archivos de ubicaciones independientes en el disco que no sean del proyecto si se llama en un entorno de producción. En el ejemplo de esta sección se comprueba el entorno de Staging llamando a IsStaging.

if (builder.Environment.IsStaging())
{
    builder.WebHost.UseStaticWebAssets();
}

Prefijo para recursos de Blazor WebAssembly

Esta sección es aplicable a Blazor Web App.

Usa la opción WebAssemblyComponentsEndpointOptions.PathPrefix punto de conexión para establecer la cadena de ruta de acceso que indica el prefijo para los recursos de Blazor WebAssembly. La ruta de acceso debe corresponder a un proyecto de aplicación de Blazor WebAssembly al que se hace referencia.

endpoints.MapRazorComponents<App>()
    .AddInteractiveWebAssemblyRenderMode(options => 
        options.PathPrefix = "{PATH PREFIX}");

En el ejemplo anterior, el marcador de posición {PATH PREFIX} es el prefijo de ruta de acceso y debe comenzar con una barra diagonal (/).

En el ejemplo siguiente, el prefijo de ruta de acceso se establece en /path-prefix:

endpoints.MapRazorComponents<App>()
    .AddInteractiveWebAssemblyRenderMode(options => 
        options.PathPrefix = "/path-prefix");

Ruta de acceso base del recurso web estático

Esta sección se aplica a las aplicaciones Blazor WebAssembly independientes.

La publicación de una aplicación coloca sus recursos estáticos, incluidos los archivos de marco de Blazor (recursos de la carpeta _framework), en la ruta raíz (/) en la salida publicada. La propiedad <StaticWebAssetBasePath> especificada en el archivo de proyecto (.csproj) establece la ruta de acceso base en una ruta de acceso no raíz:

<PropertyGroup>
  <StaticWebAssetBasePath>{PATH}</StaticWebAssetBasePath>
</PropertyGroup>

En el ejemplo anterior, el marcador de posición {PATH} es la ruta de acceso.

Sin establecer la propiedad <StaticWebAssetBasePath>, se publica una aplicación independiente en /BlazorStandaloneSample/bin/Release/{TFM}/publish/wwwroot/.

En los ejemplos anteriores, el marcador de posición {TFM} es el Moniker de la plataforma de destino (TFM) (por ejemplo, net6.0).

Si la propiedad <StaticWebAssetBasePath> en una aplicación Blazor WebAssembly independiente establece la ruta del recurso estático publicado en app1, la ruta raíz a la aplicación en la salida publicada es /app1.

En el archivo de proyecto de la aplicación independiente Blazor WebAssembly (.csproj):

<PropertyGroup>
  <StaticWebAssetBasePath>app1</StaticWebAssetBasePath>
</PropertyGroup>

En la salida publicada, la ruta de acceso a la aplicación independiente Blazor WebAssembly es /BlazorStandaloneSample/bin/Release/{TFM}/publish/wwwroot/app1/.

En los ejemplos anteriores, el marcador de posición {TFM} es el Moniker de la plataforma de destino (TFM) (por ejemplo, net6.0).

Esta sección se aplica a las aplicaciones Blazor WebAssembly independiente y a las soluciones de Blazor WebAssembly hospedadas.

La publicación de una aplicación coloca sus recursos estáticos, incluidos los archivos de marco de Blazor (recursos de la carpeta _framework), en la ruta raíz (/) en la salida publicada. La propiedad <StaticWebAssetBasePath> especificada en el archivo de proyecto (.csproj) establece la ruta de acceso base en una ruta de acceso no raíz:

<PropertyGroup>
  <StaticWebAssetBasePath>{PATH}</StaticWebAssetBasePath>
</PropertyGroup>

En el ejemplo anterior, el marcador de posición {PATH} es la ruta de acceso.

Sin establecer la propiedad <StaticWebAssetBasePath>, la aplicación cliente de una solución hospedada o una aplicación independiente se publica en las rutas de acceso siguientes:

  • En el proyecto Server de una solución de Blazor WebAssembly hospedada: /BlazorHostedSample/Server/bin/Release/{TFM}/publish/wwwroot/
  • En una aplicación Blazor WebAssembly independiente: /BlazorStandaloneSample/bin/Release/{TFM}/publish/wwwroot/

Si la propiedad <StaticWebAssetBasePath> en el proyecto Client de una aplicación Blazor WebAssembly hospedada o de una aplicación Blazor WebAssembly independiente establece la ruta del recurso estático publicado en app1, la ruta raíz a la aplicación en la salida publicada es /app1.

En el archivo del proyecto de la aplicación Client (.csproj) o en el archivo del proyecto de la aplicación Blazor WebAssembly independiente (.csproj):

<PropertyGroup>
  <StaticWebAssetBasePath>app1</StaticWebAssetBasePath>
</PropertyGroup>

En la salida publicada:

  • Ruta a la aplicación cliente en el proyecto Server de la solución de Blazor WebAssembly hospedada: /BlazorHostedSample/Server/bin/Release/{TFM}/publish/wwwroot/app1/
  • Ruta a una aplicación Blazor WebAssembly independiente: /BlazorStandaloneSample/bin/Release/{TFM}/publish/wwwroot/app1/

La propiedad <StaticWebAssetBasePath> se usa normalmente para controlar las rutas a los recursos estáticos publicados de varias aplicaciones Blazor WebAssembly en una sola implementación hospedada. Para más información, consulte Varias aplicaciones de ASP.NET Core Blazor WebAssembly hospedadas. La propiedad también es efectiva en aplicaciones Blazor WebAssembly independientes.

En los ejemplos anteriores, el marcador de posición {TFM} es el moniker de la plataforma de destino (por ejemplo, net6.0).

Asignaciones de archivos y opciones de archivo estático

Esta sección se aplica a los archivos estáticos del lado servidor.

Para crear asignaciones de archivos adicionales con un objeto FileExtensionContentTypeProvider o configurar otros valores StaticFileOptions, use uno de los enfoques siguientes. En los ejemplos siguientes, el marcador de posición {EXTENSION} es la extensión de archivo y {CONTENT TYPE} es el tipo de contenido. El espacio de nombres de la API siguiente es Microsoft.AspNetCore.StaticFiles.

  • Configure las opciones a través de la inserción de dependencias (DI) en el archivo Program mediante StaticFileOptions:

    var provider = new FileExtensionContentTypeProvider();
    provider.Mappings["{EXTENSION}"] = "{CONTENT TYPE}";
    
    builder.Services.Configure<StaticFileOptions>(options =>
    {
        options.ContentTypeProvider = provider;
    });
    
    app.UseStaticFiles();
    
  • Pasa StaticFileOptions directamente a UseStaticFiles en el archivo Program:

    var provider = new FileExtensionContentTypeProvider();
    provider.Mappings["{EXTENSION}"] = "{CONTENT TYPE}";
    
    app.UseStaticFiles(new StaticFileOptions { ContentTypeProvider = provider });
    

Para crear asignaciones de archivos adicionales con un objeto FileExtensionContentTypeProvider o configurar otros valores StaticFileOptions, use uno de los enfoques siguientes. En los ejemplos siguientes, el marcador de posición {EXTENSION} es la extensión de archivo y {CONTENT TYPE} es el tipo de contenido.

  • Configure las opciones a través de la inserción de dependencias (DI) en el archivo Program mediante StaticFileOptions:

    using Microsoft.AspNetCore.StaticFiles;
    
    ...
    
    var provider = new FileExtensionContentTypeProvider();
    provider.Mappings["{EXTENSION}"] = "{CONTENT TYPE}";
    
    builder.Services.Configure<StaticFileOptions>(options =>
    {
        options.ContentTypeProvider = provider;
    });
    

    Este enfoque configura el mismo proveedor de archivos que se usa para servir el script Blazor. Asegúrese de que la configuración personalizada no interfiera con el servicio del script Blazor. Por ejemplo, no quite la asignación para los archivos JavaScript mediante la configuración del proveedor con provider.Mappings.Remove(".js").

  • Use dos llamadas a UseStaticFiles en el archivo Program:

    • Configure el proveedor de archivos personalizado en la primera llamada con StaticFileOptions.
    • El segundo middleware proporciona el script Blazor, que usa la configuración predeterminada de los archivos estáticos proporcionada por el marco Blazor.
    using Microsoft.AspNetCore.StaticFiles;
    
    ...
    
    var provider = new FileExtensionContentTypeProvider();
    provider.Mappings["{EXTENSION}"] = "{CONTENT TYPE}";
    
    app.UseStaticFiles(new StaticFileOptions { ContentTypeProvider = provider });
    app.UseStaticFiles();
    
  • Puede evitar interferir con el servicio de _framework/blazor.server.js mediante MapWhen para ejecutar un middleware de archivos estáticos personalizado:

    app.MapWhen(ctx => !ctx.Request.Path
        .StartsWithSegments("/_framework/blazor.server.js"),
            subApp => subApp.UseStaticFiles(new StaticFileOptions() { ... }));
    

Entrega de archivos desde varias ubicaciones

La guía de esta sección es aplicable solo a Blazor Web App.

Para proporcionar archivos desde varias ubicaciones con un CompositeFileProvider:

Ejemplo:

Cree una carpeta en el proyecto de servidor denominada AdditionalStaticAssets. Coloque una imagen en la carpeta.

Agregue la siguiente instrucción using a la parte superior del archivo Program del proyecto de servidor:

using Microsoft.Extensions.FileProviders;

En el archivo Program del proyecto de servidor antesde la llamada a UseStaticFiles, agregue el siguiente código:

var secondaryProvider = new PhysicalFileProvider(
    Path.Combine(builder.Environment.ContentRootPath, "AdditionalStaticAssets"));
app.Environment.WebRootFileProvider = new CompositeFileProvider(
    app.Environment.WebRootFileProvider, secondaryProvider);

En el componente Home de la aplicación (Home.razor) marcado, haga referencia a la imagen con una etiqueta <img>:

<img src="{IMAGE FILE NAME}" alt="{ALT TEXT}" />

En el ejemplo anterior:

  • El marcador de posición {IMAGE FILE NAME} es el nombre del archivo de imagen. No es necesario proporcionar un segmento de ruta de acceso si el archivo de imagen está en la raíz de la carpeta AdditionalStaticAssets.
  • El marcador de posición {ALT TEXT} es el texto alternativo de la imagen.

Ejecutar la aplicación.

Recursos adicionales