Compartilhar via


Hospedar e implantar ASP.NET Core Blazor WebAssembly com o Nginx

Por Andrii Annenko

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 hospedar e implantar Blazor WebAssembly que tem como destino o .NET 8, 9 ou 10 usando o Nginx.

Este artigo aborda a implantação do aplicativo diretamente em um host ou em um contêiner do Docker que inclui o Nginx e os arquivos do aplicativo publicado. A seção de hospedagem do Docker aborda a publicação do aplicativo, a cópia da saída publicada para a raiz web do Nginx na imagem do contêiner, a configuração do Nginx para o roteamento no lado do cliente e a aplicação das configurações comuns de produção.

Configuração mínima do Nginx

O arquivo a seguir nginx.conf é um exemplo mínimo de configuração do Nginx mostrando como configurar o Nginx para enviar o index.html arquivo sempre que não encontrar um arquivo correspondente no disco. Ele também orienta o Nginx a fornecer tipos MIME corretos definindo um types bloco (como alternativa, incluir um mime.types arquivo).

events { }
http {
    types {
        text/html                    html;
        text/css                     css;
        application/javascript       js mjs;
        application/json             json;
        application/manifest+json    webmanifest;

        application/wasm             wasm;

        application/octet-stream     dll pdb webcil;
    }

    server {
        listen 80;

        location / {
            root /usr/share/nginx/html;
            try_files $uri $uri/ /index.html =404;
        }
    }
}

Concluir a configuração do Nginx

O exemplo a seguir nginx.conf baseia-se na configuração mínima. Ele inclui configurações opcionais para cache, compactação, limitação de taxa e cabeçalhos de segurança. Examine os comentários e remova ou ajuste as configurações com base nos requisitos do aplicativo.

events { }
http {
    # Security hardening: Don't reveal the Nginx version in responses.
    server_tokens off;

    # Optional: Rate limiting to prevent a single client from sending too 
    # many requests.
    # Blazor WebAssembly apps can generate many requests during startup.
    limit_req_zone $binary_remote_addr zone=one:10m rate=60r/s;

    # Optional: Cache-Control policy by URI.
    # - index.html and service-worker.js: avoid caching so app updates are picked up.
    # - /_framework/*: fingerprinted assets can be cached long-term.
    map $uri $cache_control {
        default             "max-age=3600";
        /index.html         "no-cache";
        /service-worker.js  "no-cache";

        # IMPORTANT: .NET 8/9 Blazor WASM apps do not fingerprint these files
        # Uncomment if the Blazor WASM app targets .NET 8/9, remove for .NET 10
        # /_framework/blazor.boot.json        "no-cache";
        # /_framework/blazor.webassembly.js   "max-age=3600";
        # /_framework/dotnet.js               "max-age=3600";

        ~^/_framework/      "public, max-age=31536000, immutable";
        ~\.woff2?$          "public, max-age=31536000, immutable";
    }

    # MIME types for Blazor WebAssembly assets.
    types {
        text/html                           html htm;
        text/css                            css;
        application/javascript              js mjs;
        application/json                    json;
        application/manifest+json           webmanifest;
        application/wasm                    wasm;
        text/plain                          txt;
        text/xml                            xml;
        application/octet-stream            bin dll exe pdb blat dat webcil;

        # Images
        image/png                           png;
        image/jpeg                          jpg jpeg;
        image/gif                           gif;
        image/webp                          webp;
        image/avif                          avif;
        image/svg+xml                       svg;
        image/x-icon                        ico;

        # Fonts
        font/woff                           woff;
        font/woff2                          woff2;

        # Fallback for other MIME types
        application/octet-stream            *;
    }

    server {
        listen 80;

        location / {
            # Root path for static site content.
            root      /usr/share/nginx/html;

            # SPA/Blazor routing:
            # - Serve a file if it exists.
            # - Otherwise fall back to index.html.
            try_files $uri $uri/ /index.html =404;

            # Optional: Use the rate limit zone defined above.
            limit_req zone=one burst=60 nodelay;

            # Optional: Serve precompressed *.gz files (when present) instead of 
            # compressing on the fly.
            gzip_static on;

            # Optional: Caching policy based on "map $uri $cache_control" above.
            add_header Cache-Control $cache_control always;

            # Optional: Mitigate MIME sniffing.
            add_header X-Content-Type-Options "nosniff" always;
        }
    }
}

Se as ferramentas de desenvolvedor do navegador ou uma ferramenta de tráfego de rede indicarem que as solicitações estão recebendo um código de status 503 – Serviço indisponível, aumente os valores de rate e burst.

Para obter mais informações sobre a configuração do servidor Web Nginx de produção, consulte Criando arquivos de configuração NGINX Plus e NGINX.

Implantação do Docker

O Dockerfile a seguir publica um Blazor WebAssembly aplicativo e serve os arquivos estáticos do aplicativo a partir de uma imagem do Nginx.

O exemplo pressupõe que:

  • O arquivo de projeto do aplicativo é nomeado BlazorSample.csproj e localizado na raiz de contexto de build do Docker.
  • Um nginx.conf arquivo está disponível na raiz do contexto de build do Docker.

Por exemplo, Dockerfilenginx.conf e BlazorSample.csproj estão todos localizados no mesmo diretório em que o restante do Blazor código também está localizado. Nesse caso, docker build é iniciado neste diretório de trabalho.

# Build stage
# IMPORTANT: change the dotnet/sdk version to the one that your Blazor app targets
FROM --platform=$BUILDPLATFORM mcr.microsoft.com/dotnet/sdk:10.0-noble AS build
WORKDIR /source

RUN apt update \
    && apt install -y python3 \
    && dotnet workload install wasm-tools

COPY . .
RUN dotnet publish BlazorSample.csproj --output /app

# Runtime stage
FROM nginx:latest
COPY --from=build /app/wwwroot/ /usr/share/nginx/html/
COPY nginx.conf /etc/nginx/nginx.conf

Crie e execute a imagem:

docker build -t blazor-wasm-nginx .
docker run --rm -p {PORT}:80 blazor-wasm-nginx

Para obter mais informações, consulte o guia do Docker Nginx.

Implantação hospedada no Linux (Nginx)

Configure o aplicativo com ForwardedHeadersOptions para encaminhar os cabeçalhos X-Forwarded-For e X-Forwarded-Proto seguindo as orientações em Configurar ASP.NET Core para trabalhar com servidores proxy e balanceadores de carga.

Para obter mais informações sobre como definir o caminho base do aplicativo, incluindo a configuração do caminho do subaplicativo, consulte Caminho base do aplicativo no ASP.NET CoreBlazor.

Siga as diretrizes para um aplicativo SignalR do ASP.NET Core com as seguintes alterações:

  • Remova a configuração para buffer de proxy (proxy_buffering off;), pois a configuração só se aplica a SSE (Eventos Enviados pelo Servidor), que não são relevantes para as interações cliente-servidor do aplicativo do Blazor.

  • Altere o caminho location de /hubroute (location /hubroute { ... }) para o caminho do subaplicativo /{PATH} (location /{PATH} { ... }), em que o espaço reservado {PATH} é o caminho do subaplicativo.

    O exemplo a seguir configura o servidor para um aplicativo que responde a solicitações no caminho /raiz:

    http {
        server {
            ...
            location / {
                ...
            }
        }
    }
    

    O exemplo a seguir configura o caminho de subaplicativo de /blazor:

    http {
        server {
            ...
            location /blazor {
                ...
            }
        }
    }
    

Recursos adicionais