Compartir a través de


Hospedar e implementar ASP.NET Core Blazor WebAssembly con Nginx

Por Andrii Annenko

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 10 de este artículo.

Advertencia

Esta versión de ASP.NET Core ya no se admite. Para obtener más información, consulte la política de soporte de .NET y .NET Core. Para la versión actual, consulte la versión de .NET 10 de este artículo.

En este artículo se explica cómo hospedar e implementar Blazor WebAssembly como destino .NET 8, 9 o 10 mediante Nginx.

En este artículo se describe la implementación de la aplicación directamente en un host o en un contenedor de Docker que incluye Nginx y los archivos de la aplicación publicada. En la sección de hospedaje de Docker se describe la publicación de la aplicación, la copia de la salida publicada en la raíz web de Nginx en la imagen del contenedor, la configuración de Nginx para el enrutamiento del lado cliente y la aplicación de la configuración de producción común.

Configuración mínima de Nginx

El siguiente nginx.conf archivo es un ejemplo de configuración mínimo de Nginx que muestra cómo configurar Nginx para enviar el index.html archivo siempre que no pueda encontrar un archivo correspondiente en el disco. También dirige a Nginx para proporcionar tipos MIME correctos mediante la definición de un types bloque (como alternativa, incluir un mime.types archivo).

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

Completar la configuración de Nginx

El ejemplo siguiente nginx.conf se basa en la configuración mínima. Incluye la configuración opcional para el almacenamiento en caché, la compresión, la limitación de velocidad y los encabezados de seguridad. Revise los comentarios y quite o ajuste la configuración en función de los requisitos de la aplicación.

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

Si las herramientas de desarrollo del explorador o una herramienta de tráfico de red indican que las solicitudes reciben un código de estado 503- Servicio no disponible , aumente los rate valores y burst .

Para obtener más información sobre la configuración del servidor web nginx de producción, consulte Creación de archivos de configuración ngINX Plus y NGINX.

Implementación de Docker

El siguiente Dockerfile publica una aplicación Blazor WebAssembly y sirve los recursos web estáticos de dicha aplicación desde una imagen de Nginx.

En el ejemplo se supone que:

  • El archivo de proyecto de la aplicación se denomina BlazorSample.csproj y se encuentra en la raíz del contexto de compilación de Docker.
  • Hay un nginx.conf archivo disponible en la raíz del contexto de compilación de Docker.

Por ejemplo, Dockerfile, nginx.conf y BlazorSample.csproj se encuentran en el mismo directorio donde también se encuentra el resto del Blazor código. En este caso, docker build se inicia en este directorio de trabajo.

# 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

Compile y ejecute la imagen:

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

Para obtener más información, consulte la guía de Docker de Nginx.

Implementación hospedada en Linux (Nginx)

Configure la aplicación con ForwardedHeadersOptions para reenviar los X-Forwarded-For encabezados y X-Forwarded-Proto siguiendo las instrucciones de Configuración de ASP.NET Core para trabajar con servidores proxy y equilibradores de carga.

Para obtener más información sobre cómo establecer la ruta de acceso base de la aplicación, incluida la configuración de la ruta de acceso de la aplicación secundaria, consulte ASP.NET ruta de acceso base de la aplicación principalBlazor.

Siga las instrucciones para obtener una aplicación SignalR de ASP.NET Core con los siguientes cambios:

  • Quite la configuración de almacenamiento en búfer de proxy (proxy_buffering off;) porque la configuración solo se aplica a los eventos enviados por el servidor (SSE), que no son relevantes para las interacciones cliente-servidor de la aplicación Blazor.

  • Cambie la ruta de location de /hubroute (location /hubroute { ... }) a la ruta de la aplicación secundaria /{PATH} (location /{PATH} { ... }), donde el marcador de posición {PATH} es la ruta de la aplicación secundaria.

    En el ejemplo siguiente se configura el servidor para una aplicación que responde a las solicitudes en la ruta de acceso raíz /:

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

    En el ejemplo siguiente se configura la ruta de acceso de la aplicación secundaria de /blazor:

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

Recursos adicionales