Compartilhar via


Arquivos estáticos Blazor do ASP.NET Core

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 descreve a configuração do aplicativo Blazor para servir arquivos estáticos.

Para obter informações gerais sobre como servir arquivos estáticos com convenções de ponto de extremidade de roteamento de Ativos Estáticos do Mapa, consulte arquivos estáticos no ASP.NET Core antes de ler este artigo.

Ativos estáticos do framework pré-carregados Blazor

Em Blazor Web Apps, os ativos estáticos da estrutura são automaticamente pré-carregados usando Link cabeçalhos, o que permite ao navegador pré-carregar recursos antes que a página inicial seja buscada e renderizada.

Em aplicativos autônomos Blazor WebAssembly, os ativos do framework são agendados para download e cache de alta prioridade no início do processamento da página do navegador index.html quando:

  • A OverrideHtmlAssetPlaceholders propriedade MSBuild no arquivo de projeto do aplicativo (.csproj) está definida como true:

    <PropertyGroup>
      <OverrideHtmlAssetPlaceholders>true</OverrideHtmlAssetPlaceholders>
    </PropertyGroup>
    
  • O elemento <link> seguinte contendo rel="preload" está presente no conteúdo <head> de wwwroot/index.html:

    <link rel="preload" id="webassembly" />
    

Entrega de ativos estáticos em aplicativos do lado do servidor Blazor

O fornecimento de recursos estáticos é gerenciado por convenções de endpoint de roteamento ou por um middleware descrito na tabela a seguir.

Recurso API Versão .NET Descrição
Convenções de ponto de extremidade de encaminhamento de Mapear Ativos Estáticos MapStaticAssets .NET 9 ou posterior Otimiza a entrega de ativos estáticos para clientes.
Middleware de arquivos estáticos UseStaticFiles Todas as versões do .NET Fornece ativos estáticos para clientes sem as otimizações de Mapear Ativos Estáticos, mas é útil para algumas tarefas que o Mapear Ativos Estáticos não é capaz de gerenciar.

Ativos estáticos de mapa podem substituir UseStaticFiles na maioria das situações. No entanto, Mapear Ativos Estáticos é otimizado para disponibilizar os ativos a partir de locais conhecidos no aplicativo no momento da compilação e da publicação. Se o aplicativo atender ativos de outros locais, como disco ou recursos inseridos, o UseStaticFiles deverá ser usado.

O Mapa de Ativos Estáticos (MapStaticAssets) também substitui a chamada de UseBlazorFrameworkFiles em aplicativos que servem arquivos de estrutura do Blazor WebAssembly, e não é necessário chamar explicitamente UseBlazorFrameworkFiles em um Blazor Web App porque a API é chamada automaticamente ao invocar AddInteractiveWebAssemblyComponents.

Quando os modos de renderização Interativo WebAssembly ou Interativo Automático estão habilitados:

  • Blazor cria um endpoint para tornar a coleção de recursos disponível como um módulo JS.
  • A URL é emitida para o corpo da solicitação como estado de componente persistente quando um componente do WebAssembly é renderizado na página.
  • Durante a inicialização do WebAssembly, Blazor recupera a URL, importa o módulo e chama uma função para recuperar a coleção de recursos e reconstruí-la na memória. A URL é específica para o conteúdo e armazenada em cache para sempre, portanto, esse custo indireto é pago apenas uma vez por usuário até que o aplicativo seja atualizado.
  • A coleção de recursos também é exposta em uma URL legível por humanos (_framework/resource-collection.js), de modo que JS tem acesso à coleção de recursos para navegação aprimorada ou para implementar recursos de outras estruturas e componentes de terceiros.

O Middleware de Arquivo Estático (UseStaticFiles) é útil nas seguintes situações que Mapear Ativos Estáticos (MapStaticAssets) não pode processar:

  • Servindo arquivos do disco que não fazem parte do processo de compilação ou publicação, por exemplo, arquivos adicionados à pasta do aplicativo durante ou após a implantação.
  • Aplicar um prefixo de caminho a arquivos de ativo estático Blazor WebAssembly, que é abordado na seção Prefixo para ativos Blazor WebAssembly.
  • Configurando mapeamentos de arquivos de extensões para tipos de conteúdo específicos e definindo opções de arquivo estático, que é abordado na seção Mapeamentos de arquivo e opções de arquivo estático.

Saiba mais em Arquivos estáticos no ASP.NET Core.

Entregue ativos com convenções de ponto de extremidade de roteamento de Mapear Ativos Estáticos

Esta seção se aplica a aplicativos Blazor do lado do servidor.

Os ativos são entregues por meio da propriedade ComponentBase.Assets, que resolve a URL armazenada em impressão digital para um recurso específico. No exemplo a seguir, o Bootstrap, a Blazor folha de estilo do aplicativo do modelo de projeto (app.css), e a folha de estilo de isolamento CSS (com base no namespace de um aplicativo de BlazorSample) estão vinculados em um componente raiz, normalmente o componente App (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"]" />

Componente ImportMap

Esta seção se aplica a Blazor Web Apps que chamam MapRazorComponents.

O ImportMap componente (ImportMap) representa um elemento de mapa de importação (<script type="importmap"></script>) que define o mapa de importação para scripts de módulo. O componente Mapa de importação é colocado no conteúdo <head> do componente raiz, normalmente no componente App (Components/App.razor).

<ImportMap />

Se um ImportMapDefinition customizado não for atribuído a um componente Mapa de Importação, o mapa de importação será gerado com base nos recursos do aplicativo.

Observação

ImportMapDefinition as instâncias são caras de criar, portanto, recomendamos armazenar em cache ao criar uma instância adicional.

Os exemplos a seguir demonstram definições de mapas de importação personalizados e os mapas de importação que eles criam.

Mapa de importação básico:

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

O código anterior resulta no seguinte mapa de importação:

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

Importar mapa com escopo:

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

O código anterior resulta no seguinte mapa de importação:

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

Importar mapa com integridade:

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" },
    });

O código anterior resulta no seguinte mapa de importação:

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

Combine as definições do mapa de importação (ImportMapDefinition) com ImportMapDefinition.Combine.

Mapa de importação criado a partir de ResourceAssetCollection que mapeia ativos estáticos para suas URLs exclusivas correspondentes:

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

O código anterior resulta no seguinte mapa de importação:

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

Importar mapa das violações da CSP (Política de Segurança de Conteúdo)

Esta seção se aplica a Blazor Web Apps que chamam MapRazorComponents.

O componente ImportMap é renderizado como uma tag embutida <script>, o que viola uma Política de Segurança de Conteúdo (CSP) estrita que define a diretiva default-src ou script-src.

Para obter exemplos de como abordar a violação de políticas com SRI (Subresource Integrity) ou um nonce criptográfico, consulte Resolvendo violações de CSP com SRI (Subresource Integrity) ou um nonce.

Configure o Middleware de arquivos estáticos para fornecer ativos estáticos aos clientes chamando UseStaticFiles no pipeline de processamento de solicitação do aplicativo. Saiba mais em Arquivos estáticos no ASP.NET Core.

Em versões anteriores ao .NET 8, os arquivos estáticos da estrutura Blazor, como o script Blazor, são atendidos por meio do Middleware de Arquivo Estático. No .NET 8 ou versões posteriores, os arquivos estáticos do framework Blazor são mapeados usando roteamento de endpoints, e o Middleware de Arquivo Estático não é mais utilizado.

Ativos estáticos do lado do cliente de impressão digital em aplicativos Blazor WebAssembly autônomos

Em aplicativos Blazor WebAssembly autônomos, durante a compilação/publicação, a estrutura substitui espaços reservados em index.html por valores calculados durante a compilação para ativos estáticos de impressão digital para renderização do lado do cliente. Uma impressão digital é colocada no nome do arquivo de script blazor.webassembly.js e um mapa de importação é gerado para outros ativos do .NET.

A seguinte configuração deve estar presente no arquivo wwwwoot/index.html de um aplicativo Blazor WebAssembly autônomo para adotar a impressão digital:

<head>
    ...
    <script type="importmap"></script>
    ...
</head>

<body>
    ...
    <script src="_framework/blazor.webassembly#[.{fingerprint}].js"></script>
    ...
</body>

</html>

No arquivo de projeto (.csproj), a <OverrideHtmlAssetPlaceholders> propriedade é definida como true:

<PropertyGroup>
  <OverrideHtmlAssetPlaceholders>true</OverrideHtmlAssetPlaceholders>
</PropertyGroup>

Ao resolver as importações para a interoperabilidade do JavaScript, o mapa de importação é usado pelo navegador para resolver arquivos com impressão digital.

Qualquer script em index.html com o marcador de impressão digital é identificado pela estrutura. Por exemplo, um arquivo de script nomeado scripts.js na pasta wwwroot/js do aplicativo é registrado ao se adicionar #[.{fingerprint}] antes da extensão do arquivo (.js).

<script src="js/scripts#[.{fingerprint}].js"></script>

Ativos estáticos do lado do cliente de impressão digital em Blazor Web Apps

Para CSR (renderização do lado do cliente) em Blazor Web Apps (modos de renderização interativa automática ou interativa webAssembly), a impressão digital estática do lado do servidor do ativo é habilitada adotando convenções de ponto de extremidade de roteamento de Ativos Estáticos do Mapa (MapStaticAssets), componente ImportMap e a propriedade ComponentBase.Assets (@Assets["..."]). Saiba mais em Arquivos estáticos no ASP.NET Core.

Para a identificação de módulos JavaScript adicionais para CSR, use o item <StaticWebAssetFingerprintPattern> no arquivo de projeto do aplicativo .csproj. No exemplo a seguir, uma impressão digital é adicionada para todos os arquivos fornecidos pelo .mjs desenvolvedor no aplicativo:

<ItemGroup>
  <StaticWebAssetFingerprintPattern Include="JSModule" Pattern="*.mjs" 
    Expression="#[.{fingerprint}]!" />
</ItemGroup>

Ao resolver as importações para a interoperabilidade do JavaScript, o mapa de importação é usado pelo navegador para resolver arquivos com impressão digital.

Esta seção se aplica a todas as versões .NET eBlazor aplicativos.

As tabelas a seguir resumem os formatos de arquivos estáticos por versão do .NET.

Para saber o local do conteúdo <head> em que os links de arquivos estáticos são colocados, consulte ASP.NET Core Blazor estrutura do projeto. Os links de ativos estáticos também podem ser fornecidos usando <HeadContent> componentes em componentes individuaisRazor.

Para saber o local do conteúdo <head> em que os links de arquivos estáticos são colocados, consulte ASP.NET Core Blazor estrutura do projeto.

.NET 9 ou posterior

Tipo de aplicativo Valor href Exemplos
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" />
Blazor WebAssembly autônomo {PATH} <link rel="stylesheet" href="css/app.css" />
<link href="_content/ComponentLib/styles.css" rel="stylesheet" />

.NET 8.x

Tipo de aplicativo Valor href Exemplos
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" />
Blazor WebAssembly autônomo {PATH} <link rel="stylesheet" href="css/app.css" />
<link href="_content/ComponentLib/styles.css" rel="stylesheet" />

.NET 7.x ou anterior

Tipo de aplicativo Valor href Exemplos
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 é compatível com o .NET 8 ou posterior, mas não é mais um modelo de projeto após o .NET 7.
‡Recomendamos atualizar os Blazor WebAssembly aplicativos hospedados para Blazor Web Apps, ao adotar .NET 8 ou posterior.

Modo de projeto de ativo da Web estático

Esta seção se aplica ao projeto .Client de um Blazor Web App.

A configuração necessária <StaticWebAssetProjectMode>Default</StaticWebAssetProjectMode> no projeto .Client de um Blazor Web App reverte comportamentos de ativos estáticos Blazor WebAssembly de volta para os padrões, para que o projeto se comporte como parte do projeto hospedado. O SDK Blazor WebAssembly (Microsoft.NET.Sdk.BlazorWebAssembly) configura ativos da Web estáticos de uma maneira específica para funcionar no modo "autônomo" com um servidor simplesmente consumindo as saídas da biblioteca. Isso não é apropriado para um Blazor Web App, em que a parte WebAssembly do aplicativo é uma parte lógica do host e precisa se comportar mais como uma biblioteca. Por exemplo, o projeto não expõe o pacote de estilos (por exemplo, BlazorSample.Client.styles.css) e, em vez disso, fornece apenas ao host o pacote do projeto, para que o host possa incluí-lo no próprio pacote de estilos.

Não é possível alterar o valor (Default) de <StaticWebAssetProjectMode> ou remover a propriedade do projeto .Client.

Prefixo para Blazor WebAssembly ativos

Esta seção aplica-se a Blazor Web Apps.

Use a opção de ponto de extremidade WebAssemblyComponentsEndpointOptions.PathPrefix para definir a cadeia de caracteres do caminho que indica o prefixo para os ativos Blazor WebAssembly. O caminho deve corresponder a um projeto de aplicativo referenciado Blazor WebAssembly.

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

No exemplo anterior, o {PATH PREFIX} espaço reservado é o prefixo do caminho e deve começar com uma barra (/).

No exemplo a seguir, o prefixo de caminho é definido como /path-prefix:

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

Caminho de base do ativo da Web estático

Esta seção se aplica a aplicativos Blazor WebAssembly autônomos.

A publicação do aplicativo coloca os ativos estáticos do aplicativo, incluindo os Blazor arquivos de estrutura (_framework ativos da pasta), no caminho raiz (/) na saída publicada. A propriedade <StaticWebAssetBasePath> especificada no arquivo de projeto (.csproj) define o caminho base como um caminho não raiz:

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

No exemplo anterior, o espaço reservado {PATH} é o caminho.

Sem definir a propriedade <StaticWebAssetBasePath>, um aplicativo autônomo é publicado em /BlazorStandaloneSample/bin/Release/{TFM}/publish/wwwroot/.

No exemplo anterior, o {TFM} espaço reservado é o Target Framework Moniker (TFM).

Se a propriedade <StaticWebAssetBasePath> em um aplicativo Blazor WebAssembly autônomo definir o caminho do ativo estático publicado como app1, o caminho raiz para o aplicativo na saída publicada será /app1.

No arquivo do projeto de aplicativo Blazor WebAssembly autônomo (.csproj):

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

Na saída publicada, o caminho para o aplicativo autônomo Blazor WebAssembly é /BlazorStandaloneSample/bin/Release/{TFM}/publish/wwwroot/app1/.

No exemplo anterior, o {TFM} espaço reservado é o Target Framework Moniker (TFM).

Esta seção se aplica a aplicativos autônomos Blazor WebAssembly e soluções hospedadas Blazor WebAssembly.

A publicação do aplicativo coloca os ativos estáticos do aplicativo, incluindo os Blazor arquivos de estrutura (_framework ativos da pasta), no caminho raiz (/) na saída publicada. A propriedade <StaticWebAssetBasePath> especificada no arquivo de projeto (.csproj) define o caminho base como um caminho não raiz:

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

No exemplo anterior, o espaço reservado {PATH} é o caminho.

Sem definir a propriedade <StaticWebAssetBasePath>, o aplicativo cliente de uma solução hospedada ou um aplicativo autônomo é publicado nos seguintes caminhos:

  • No projeto Server de uma solução hospedada Blazor WebAssembly: /BlazorHostedSample/Server/bin/Release/{TFM}/publish/wwwroot/
  • Em um aplicativo autônomo Blazor WebAssembly: /BlazorStandaloneSample/bin/Release/{TFM}/publish/wwwroot/

Se a propriedade <StaticWebAssetBasePath> no projeto Client de um aplicativo hospedado Blazor WebAssembly ou em um aplicativo autônomo Blazor WebAssembly definir o caminho do ativo estático publicado como app1, o caminho raiz para o aplicativo na saída publicada será /app1.

No arquivo de projeto do aplicativo Client (.csproj) ou no arquivo de projeto do aplicativo autônomo Blazor WebAssembly (.csproj):

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

Na saída publicada:

  • Caminho para o aplicativo cliente no projeto Server de uma solução hospedada Blazor WebAssembly: /BlazorHostedSample/Server/bin/Release/{TFM}/publish/wwwroot/app1/
  • Caminho para um aplicativo autônomo Blazor WebAssembly: /BlazorStandaloneSample/bin/Release/{TFM}/publish/wwwroot/app1/

A propriedade <StaticWebAssetBasePath> é mais comumente usada para controlar os caminhos para recursos estáticos publicados de vários aplicativos Blazor WebAssembly em um único ambiente hospedado. Para obter mais informações, confira Vários aplicativos Blazor WebAssembly do ASP.NET Core hospedados. A propriedade também é eficaz em aplicativos autônomos Blazor WebAssembly.

Nos exemplos anteriores, o {TFM} marcador de posição é o Target Framework Moniker (TFM).

Mapeamentos de arquivos e opções para arquivos estáticos

Esta seção se aplica a arquivos estáticos do lado do servidor.

Para criar mapeamentos de arquivo adicionais com FileExtensionContentTypeProvider ou configurar outro StaticFileOptions, use uma das abordagens a seguir. Nos exemplos a seguir, o espaço reservado {EXTENSION} é a extensão de arquivo e o espaço reservado {CONTENT TYPE} é o tipo de conteúdo.

  • Configure opções por meio da injeção de dependência (DI) no arquivo Program usando StaticFileOptions:

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

    Essa abordagem configura o mesmo provedor de arquivos usado para atender ao script Blazor. Certifique-se de que a configuração personalizada não interfira no serviço do script Blazor. Por exemplo, não remova o mapeamento para arquivos JavaScript configurando o provedor com provider.Mappings.Remove(".js").

  • Use duas chamadas para UseStaticFiles no arquivo Program:

    • Configure o provedor de arquivos personalizado na primeira chamada com StaticFileOptions.
    • O segundo middleware atende ao script Blazor, que usa a configuração de arquivos estáticos padrão fornecida pela estrutura Blazor.
    using Microsoft.AspNetCore.StaticFiles;
    
    ...
    
    var provider = new FileExtensionContentTypeProvider();
    provider.Mappings["{EXTENSION}"] = "{CONTENT TYPE}";
    
    app.UseStaticFiles(new StaticFileOptions { ContentTypeProvider = provider });
    app.UseStaticFiles();
    
  • Você pode evitar interferir na distribuição de _framework/blazor.server.js usando MapWhen para executar um middleware de arquivo estático personalizado.

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

Servir arquivos de vários locais

As diretrizes nesta seção se aplicam apenas a Blazor Web Apps.

Para disponibilizar arquivos de vários locais com um CompositeFileProvider:

Exemplo:

Crie uma nova pasta no projeto do servidor chamado AdditionalStaticAssets. Coloque uma imagem na pasta.

Adicione a seguinte instrução using à parte superior do arquivo Program do projeto de servidor:

using Microsoft.Extensions.FileProviders;

No arquivo Program do projeto do servidor antes de a chamada para UseStaticFiles, adicione o seguinte código:

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

Na marcação do componente Home do aplicativo (Home.razor), faça referência à imagem com uma marca de <img> :

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

No exemplo anterior:

  • O espaço reservado {IMAGE FILE NAME} representa o nome do arquivo da imagem. Não é necessário fornecer um segmento de caminho se o arquivo de imagem estiver na raiz da pasta AdditionalStaticAssets.
  • O espaço reservado {ALT TEXT} é o texto alternativo da imagem.

Execute o aplicativo.

Recursos adicionais