Compartilhar via


Arquivos estáticos Blazor do ASP.NET Core

Observação

Esta não é a versão mais recente deste artigo. Para informações sobre a versão vigente, confira a Versão do .NET 8 deste artigo.

Aviso

Esta versão do ASP.NET Core não tem mais suporte. Para obter mais informações, confira .NET e a Política de Suporte do .NET Core. Para informações sobre a versão vigente, confira a Versão do .NET 8 deste artigo.

Importante

Essas informações relacionam-se ao produto de pré-lançamento, que poderá ser substancialmente modificado antes do lançamento comercial. A Microsoft não oferece nenhuma garantia, explícita ou implícita, quanto às informações fornecidas aqui.

Para informações sobre a versão vigente, confira a Versão do .NET 8 deste artigo.

Este artigo descreve a configuração do aplicativo Blazor para servir arquivos estáticos.

Middleware de ativo estático

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

O serviço de ativos estáticos é gerenciado por qualquer um dos dois middlewares descritos na tabela a seguir.

Middleware API Versão .NET Descrição
Mapear ativos estáticos MapStaticAssets .NET 9 ou posterior Otimiza a entrega de ativos estáticos para clientes.
Arquivos estáticos UseStaticFiles Todas as versões do .NET Serve ativos estáticos para clientes sem as otimizações de MapStaticAssets mas úteis para algumas tarefas que MapStaticAssets não é capaz de gerenciar.

Configure o Middleware de Ativos Estáticos do Mapa chamando MapStaticAssets no pipeline de processamento de solicitações do aplicativo, que executa o seguinte:

MapStaticAssets opera combinando processos de compilação e publicação para coletar informações sobre os ativos estáticos no aplicativo. Essas informações são utilizadas pela biblioteca de runtime para atender com eficiência os ativos estáticos aos navegadores.

MapStaticAssets pode substituir UseStaticFiles na maioria das situações. No entanto, MapStaticAssets é otimizado para atender os ativos de locais conhecidos no aplicativo no tempo de compilação e publicação. Se o aplicativo atender ativos de outros locais, como disco ou recursos inseridos, o UseStaticFiles deverá ser usado.

MapStaticAssets oferece os seguintes benefícios que não estão disponíveis ao chamar UseStaticFiles:

  • Compactação em tempo de compilação de todos os ativos do aplicativo, incluindo JavaScript (JS) e folhas de estilo, mas excluindo ativos de imagem e fonte que já estão compactados. A compactação Gzip (Content-Encoding: gz) é usada durante o desenvolvimento. A compactação Gzip com Brotli (Content-Encoding: br) é usada durante a publicação.
  • Impressão digital para todos os ativos no momento da compilação com uma cadeia de caracteres codificada em Base64 do hash SHA-256 do conteúdo de cada arquivo. Isso impede a reutilização de uma versão antiga de um arquivo, mesmo que o arquivo antigo esteja armazenado em cache. Os ativos com impressão digital são armazenados em cache usando a diretiva immutable, o que faz com que o navegador nunca solicite o ativo novamente até que ele seja alterado. Para navegadores sem suporte para a diretiva immutable, uma diretiva max-age é adicionada.
    • Mesmo que um ativo não tenha impressão digital, o conteúdo baseado em ETags é gerado para cada ativo estático usando o hash de impressão digital do arquivo como o valor ETag. Isso garante que o navegador só faça o download de um arquivo se o seu conteúdo for alterado (ou se o arquivo estiver sendo baixado pela primeira vez).
    • Internamente, o Blazor mapeia os ativos físicos para suas impressões digitais, o que permite que o aplicativo:
      • Encontre ativos Blazor gerados automaticamente, como RazorCSS com escopo de componente para o recurso de Blazor isolamento de CSS, e ativos JS descritos por JS mapas de importação.
      • Gerar marcas de link no conteúdo <head> da página para pré-carregar ativos.
  • Durante o testes de desenvolvimento do Visual Studio Hot Reload:
    • As informações de integridade são removidas dos ativos para evitar problemas quando um arquivo é alterado enquanto o aplicativo está em execução.
    • Os ativos estáticos não são armazenados em cache para garantir que o navegador sempre recupere o conteúdo atual.

Quando os modos de renderização Interativa WebAssembly ou Interativa Automática estão habilitados:

  • Blazor cria um ponto de extremidade para expor a coleção de recursos 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 Mapeamento de Ativos Estáticos não oferece recursos para minificação ou outras transformações de arquivos. A minificação geralmente é gerenciada por código personalizado ou por ferramentas de terceiros.

O Middleware de Arquivo Estático (UseStaticFiles) é útil nas seguintes situações que MapStaticAssets não podem lidar:

Consuma ativos com o Middleware de Mapeamento de Arquivos Estáticos

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

Os ativos são consumidos por meio da propriedade ComponentBase.Assets, que resolve a URL com impressão digital para um determinado ativo. No exemplo a seguir, Bootstrap, a folha de estilos do aplicativo do modelo de projeto Blazor (app.css), e a folha de estilos de isolamento de CSS são vinculadas em um componente raiz, tipicamente 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["BlazorWeb-CSharp.styles.css"]" />

Mapas de importação

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

O 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 ImportMap é colocado no conteúdo <head> do componente raiz, normalmente o componente App (Components/App.razor).

<ImportMap />

Se um ImportMapDefinition personalizado não for atribuído a um componente ImportMap, o mapa de importação será gerado com base nos ativos do aplicativo.

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"
  }
}

Mapa de importação 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"
    }
  }
}

Mapa de importação 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"
  }
}

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 posterior, os arquivos estáticos da estrutura Blazor são mapeados usando o roteamento de ponto de extremidade e o Middleware de Arquivo Estático não é mais usado.

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

As tabelas a seguir resumem os formatos de arquivo estático <link> href 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> e clmpactocomponentes em componentes Razor individuais.

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 href valor Exemplos
Aplicativo Web Blazor @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 href valor Exemplos
Aplicativo Web Blazor {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 href valor 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 aplicativos hospedados Blazor WebAssembly para Blazor Aplicativos Web ao adotar o .NET 8 ou posterior.

Modo de projeto de ativo da Web estático

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

A configuração necessária <StaticWebAssetProjectMode>Default</StaticWebAssetProjectMode> no projeto .Client de um aplicativo Web Blazor 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 aplicativo Web Blazor, onde 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.

A alteração do valor (Default) de <StaticWebAssetProjectMode> ou remoção da propriedade do projeto .Clientnão tem suporte.

Arquivos estáticos em ambientes não Development estáticos

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

Ao executar um aplicativo localmente, os ativos da Web estáticos só são habilitados por padrão no ambiente Development. Para habilitar arquivos estáticos para ambientes diferentes de Development durante o desenvolvimento e teste local (por exemplo, Staging), chame UseStaticWebAssets no WebApplicationBuilder no arquivo Program.

Aviso

Chame UseStaticWebAssets para o ambiente exato para impedir a ativação do recurso em produção, pois ele atende arquivos de locais separados em disco diferente do projeto, se chamado em um ambiente de produção. O exemplo nesta seção verifica o ambiente Staging chamando IsStaging.

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

Prefixo para Blazor WebAssembly ativos

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

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.

Por padrão, a publicação do aplicativo coloca os ativos estáticos do aplicativo, incluindo arquivos de estrutura Blazor (_framework ativos de 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 espaço reservado {TFM} é o Moniker da Estrutura de Destino (TFM) (por exemplo, net6.0).

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 espaço reservado {TFM} é o Moniker da Estrutura de Destino (TFM) (por exemplo, net6.0).

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

Por padrão, a publicação do aplicativo coloca os ativos estáticos do aplicativo, incluindo arquivos de estrutura Blazor (_framework ativos de 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 ativos estáticos publicados de vários aplicativos Blazor WebAssembly em uma única implantação hospedada. 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 espaço reservado {TFM} é o TFM (Moniker da Estrutura de Destino) (por exemplo, net6.0).

Mapeamentos de arquivo e opções de arquivo estático

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. O namespace da API a seguir é Microsoft.AspNetCore.StaticFiles.

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

    var provider = new FileExtensionContentTypeProvider();
    provider.Mappings["{EXTENSION}"] = "{CONTENT TYPE}";
    
    builder.Services.Configure<StaticFileOptions>(options =>
    {
        options.ContentTypeProvider = provider;
    });
    
    app.UseStaticFiles();
    
  • Passe o StaticFileOptions diretamente para UseStaticFiles no arquivo Program:

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

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 no atendimento 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() { ... }));
    

Recursos adicionais