Configura el comportamiento del hosting

Firebase Hosting te permite configurar comportamientos de hosting personalizados, como páginas de error, redireccionamientos, reescrituras y encabezados personalizados. Además, te permite especificar qué archivos del directorio del proyecto quieres implementar en el proyecto de Firebase.

Define la configuración de Firebase Hosting en el archivo firebase.json.

Encontrarás el archivo firebase.json en la raíz del directorio del proyecto. Cuando ejecutas el comando firebase init, Firebase crea automáticamente el archivo firebase.json.

.

Al final de esta página, se presenta un ejemplo de configuración completo de firebase.json (solo abarca Firebase Hosting). Ten en cuenta que un archivo firebase.json también puede contener configuraciones de otros servicios de Firebase.

Puedes verificar el contenido implementado de firebase.json mediante la API de REST de Hosting.

Orden de prioridad de las respuestas de Hosting

En ocasiones, las diversas opciones de configuración de Firebase Hosting que se describen en esta página se pueden sobreponer. Si hay un conflicto, Hosting determina su respuesta en este orden de prioridad:

  1. Espacios de nombres reservados que comienzan con un segmento de ruta de acceso /__/*
  2. Redireccionamientos configurados
  3. Contenido estático de concordancia exacta
  4. Reescrituras configuradas
  5. Página 404 personalizada
  6. Página 404 predeterminada

Especifica qué archivos se deben implementar

Los atributos predeterminados public y ignore, que se incluyen en el archivo firebase.json predeterminado, definen qué archivos del directorio del proyecto se deben implementar en el proyecto de Firebase.

La configuración predeterminada de hosting del archivo firebase.json tiene este aspecto:

"hosting": {
  "public": "public",  // the only required attribute for hosting
  "ignore": [
    "firebase.json",
    "**/.*",
    "**/node_modules/**"
  ]
}

public

Obligatorio
El atributo public especifica qué directorio se debe implementar en Firebase Hosting. El valor predeterminado es un directorio llamado public, pero puedes especificar la ruta de acceso de cualquier directorio, siempre que exista en el directorio del proyecto.

Este es el nombre especificado predeterminado del directorio que se debe implementar:

"hosting": {
  "public": "public"

  // ...
}

Puedes cambiar el valor predeterminado por el del directorio que quieres implementar:

"hosting": {
  "public": "dist/app"

  // ...
}

ignore

Opcional
El atributo ignore especifica qué archivos se deben pasar por alto en la implementación. Puede usar los globs de la misma manera que Git controla .gitignore.

Estos son los valores predeterminados de los archivos que se deben pasar por alto:

"hosting": {
  // ...

  "ignore": [
    "firebase.json",  // the Firebase configuration file (this file)
    "**/.*",  // files with a leading period should be hidden from the system
    "**/node_modules/**"  // contains dependencies used to create your site but not run it
  ]
}

Personaliza una página 404/“Not Found”

Opcional
Puedes especificar que se muestre un error 404 Not Found personalizado cuando un usuario trate de acceder a una página inexistente.

Crea un archivo nuevo en el directorio public del proyecto, denomínalo 404.html y agrega el contenido personalizado de 404 Not Found al archivo.

Firebase Hosting mostrará el contenido de esta página 404.html personalizada si un navegador activa un error 404 Not Found en el dominio o subdominio.

Configura redireccionamientos

Opcional
Usa el redireccionamiento de URL a fin de evitar la presencia de vínculos rotos si transferiste una página, o bien para acortar URL. Por ejemplo, puedes redireccionar a un navegador de example.com/team a example.com/about.html.

Especifica los redireccionamientos de la URL creando un atributo redirects con un arreglo de objetos denominado “reglas de redireccionamiento”. En cada regla debes especificar un patrón de URL que active Hosting para que redireccione a la URL de destino especificada (si coincide con la ruta de URL de la solicitud).

Este es un atributo redirects de ejemplo:

"hosting": {
  // ...

  // Add the "redirects" attribute within "hosting"
  "redirects": [ {
    // Returns a permanent redirect to "/bar" for requests to "/foo" (but not "/foo/**")
    "source": "/foo",
    "destination": "/bar",
    "type": 301
  }, {
    // Returns a permanent redirect to "/bar" for requests to both "/foo" and "/foo/**"
    "source": "/foo{,/**}"
    "destination": "/bar"
    "type": 301
  }, {
    // Returns a temporary redirect for all requests to files or directories in the "firebase" directory
    "source": "/firebase/**",
    "destination": "https://firebase.google.com/",
    "type": 302
  }, {
    // A regular expression-based redirect equivalent to the above behavior
    "regex": "/firebase/.*",
    "destination": "https://firebase.google.com/",
    "type": 302
  } ]
}

El atributo redirects contiene un arreglo de reglas de redireccionamiento, en el que cada una debe incluir los siguientes campos:

  • source o regex: Especifica un patrón de URL que activa Hosting para aplicar el redireccionamiento si coincide con la URL de la solicitud.

  • destination: Especifica una URL estática que puede ser una ruta relativa o absoluta.

  • type: Especifica el código de respuesta HTTP.

    • Usa un tipo de 301 para “Transferido permanentemente”.
    • Usa un tipo de 302 para “Encontrado” (redireccionamiento temporal).

Firebase Hosting compara los valores source o regex con todas las rutas de URL al inicio de cada solicitud (antes de que el navegador determine si existe un archivo o una carpeta en esa ruta). Si se encuentra una coincidencia, el servidor de origen de Firebase Hosting enviará una respuesta de redireccionamiento HTTP para indicar al navegador que debe realizar una solicitud nueva en la URL destination.

Captura segmentos de URL para los redireccionamientos

Opcional
A veces es posible que debas capturar segmentos específicos del patrón de URL de una regla de redireccionamiento (valor source o regex) y, luego, volver a utilizarlos en la ruta destination de la regla.

Captura segmentos de URL cuando uses globs

Si usas un campo source (es decir, especificas un glob para tu patrón de URL), puedes capturar segmentos. Para ello incluye un prefijo : a fin de identificar el segmento. También incluye un * justo después del segmento si necesitas capturar la ruta de URL que le sucede. Por ejemplo:

"hosting": {
  // ...

  "redirects": [ {
    "source": "/blog/:post*",  // captures the entire URL segment beginning at "post"
    "destination": "https://blog.myapp.com/:post", // includes the entire URL segment identified and captured by the "source" value
    "type": 301
  }, {
    "source": "/users/:id/profile",  // captures only the URL segment "id", but nothing following
    "destination": "/users/:id/newProfile",  // includes the URL segment identified and captured by the "source" value
    "type": 301
  } ]
}

Captura segmentos de URL cuando uses expresiones regulares RE2

Si usas un campo regex (es decir, especificas una expresión regular RE2 para tu patrón de URL), puedes capturar segmentos con grupos de captura RE2 con o sin nombre. Los grupos de captura con nombre se pueden usar en el campo destination con un prefijo :, y los que no tienen nombre se pueden referenciar por su índice numérico en el valor regex, indexado desde 1. Por ejemplo:

"hosting": {
  // ...

  "redirects": [ {
    "regex": "/blog/(?P<post>.+)",  // if you're familiar with PCRE, be aware that RE2 requires named capture groups to begin with ?P
    "destination": "https://blog.myapp.com/:post",  // includes the entire URL segment identified and captured by the `regex` value
    "type": 301
  }, {
    "regex": "/users/(\d+)/profile",  // uses the \d directive to only match numerical path segments
    "destination": "/users/:1/newProfile",  // the first capture group to be seen in the `regex` value is named 1, and so on
    "type": 301
  } ]
}

Configura reescrituras

Opcional
Usa una reescritura para mostrar el mismo contenido en varias URL. Las reescrituras son especialmente útiles con la coincidencia de patrones, ya que puedes aceptar cualquier URL que coincida con el patrón y permitir que el código del cliente decida qué mostrar.

Las reescrituras también sirven para admitir apps que usan HTML5 pushState a fin de navegar. Cuando un navegador intente abrir una ruta de URL que coincida con el patrón de URL source o regex específico, el navegador le proporcionará el contenido del archivo en la URL destination.

Crea un atributo rewrites que contenga un arreglo de objetos denominado “reglas de reescritura” para especificar las reescrituras de URL. Especifica en cada regla un patrón de URL que active Hosting para que responda como si se le otorgara al servicio la URL de destino especificada (si coincide con la ruta de URL de la solicitud).

Este es un atributo rewrites de ejemplo:

"hosting": {
  // ...

  // Add the "rewrites" attribute within "hosting"
  "rewrites": [ {
    // Serves index.html for requests to files or directories that do not exist
    "source": "**",
    "destination": "/index.html"
  }, {
    // Serves index.html for requests to both "/foo" and "/foo/**"
    // Using "/foo/**" only matches paths like "/foo/xyz", but not "/foo"
    "source": "/foo{,/**}",
    "destination": "/index.html"
  }, {
    // A regular expression-based rewrite equivalent to the above behavior
    "regex": "/foo(/.*)?",
    "destination": "/index.html"
  }, {
    // Excludes specified pathways from rewrites
    "source": "!/@(js|css)/**",
    "destination": "/index.html"
  } ]
}

El atributo rewrites contiene un arreglo de reglas de reescritura, en el que cada regla debe incluir los siguientes campos:

  • source o regex: Especifica un patrón de URL que activa Hosting para aplicar la reescritura (si coincide con la URL de la solicitud).

  • destination: Especifica un archivo local existente.

Firebase Hosting solo aplicará una regla de reescritura si un archivo o directorio no existe en la ruta de URL que coincide con el patrón de URL source o regex especificado. Cuando se activa una regla de reescritura, el navegador muestra el contenido del archivo destination especificado, en lugar de un redireccionamiento HTTP.

Dirige las solicitudes a una función

Puedes usar rewrites para entregar funciones desde una URL de Firebase Hosting. El siguiente ejemplo es un extracto del artículo sobre cómo entregar contenido dinámico con Cloud Functions.

Por ejemplo, para indicar que todas las solicitudes de la página /bigben del sitio de Hosting ejecuten la función bigben, haz lo siguiente:

"hosting": {
  // ...

  // Add the "rewrites" attribute within "hosting"
  "rewrites": [ {
    "source": "/bigben",
    "function": "bigben"
  } ]
}

Después de agregar esta regla de reescritura y de implementarla en Firebase (con firebase deploy), puedes acceder a la función a través de las siguientes URL:

  • Tus subdominios de Firebase: projectID.web.app/bigben y projectID.firebaseapp.com/bigben

  • Cualquier dominio personalizado conectado: custom-domain/bigben

Dirige las solicitudes a un contenedor de Cloud Run

Puedes usar rewrites para acceder a un contenedor de Cloud Run desde una URL de Firebase Hosting. El siguiente ejemplo es un extracto del artículo sobre cómo entregar contenido dinámico con Cloud Run.

Por ejemplo, para indicar que todas las solicitudes de la página /helloworld del sitio de Hosting activen el inicio y la ejecución de una instancia de contenedor llamada helloworld, haz lo siguiente:

"hosting": {
 // ...

 // Add the "rewrites" attribute within "hosting"
 "rewrites": [ {
   "source": "/helloworld",
   "run": {
     "serviceId": "helloworld",  // "service name" (from when you <a href="#deploy">deployed the container image)</a>
     "region": "us-central1"     // optional (if omitted, default is us-central1)
   }
 } ]
}

Después de agregar esta regla de reescritura y de implementarla en Firebase (con firebase deploy), puedes acceder a la imagen de contenedor a través de las siguientes URL:

  • Tus subdominios de Firebase: projectID.web.app/helloworld y projectID.firebaseapp.com/helloworld

  • Cualquier dominio personalizado conectado: custom-domain/helloworld

Puedes usar rewrites para crear Dynamic Links de dominios personalizados. Consulta la documentación de Dynamic Links a fin de obtener información detallada sobre cómo configurar un dominio personalizado para Dynamic Links.

Por ejemplo, puede hacer lo siguiente:

  • Usa tu dominio solo para Dynamic Links:

    "hosting": {
      // ...
    
      "appAssociation": "AUTO",  // required for Dynamic Links (default is AUTO if not specified)
    
      // Add the "rewrites" attribute within "hosting"
      "rewrites": [ {
        "source": "/**",  // Dynamic Links start with "https://<your-domain>/"
        "dynamicLinks": true
      } ]
    }
    
  • Especifica los prefijos de ruta que quieras usar para los Dynamic Links:

    "hosting": {
      // ...
    
      "appAssociation": "AUTO",  // required for Dynamic Links (default is AUTO if not specified)
    
      // Add the "rewrites" attribute within "hosting"
      "rewrites": [ {
        "source": "/promos/**",  // Dynamic Links can start with "https://<your-domain>/promos/"
        "dynamicLinks": true
      }, {
        "source": "/links/share/**",  // Dynamic Links can start with "https://<your-domain>/links/share/"
        "dynamicLinks": true
      } ]
    }
    

Para configurar Dynamic Links en el archivo firebase.json, necesitas lo siguiente:

  • Un atributo appAssociation configurado como AUTO

    • El valor predeterminado de appAssociation será AUTO si no se incluye el atributo en la configuración.
    • Si el atributo se configura como AUTO, Hosting generará los archivos assetlinks.jsonapple-app-site-association de manera dinámica cuando estos se soliciten.
  • Un atributo rewrites para Dynamic Links con un arreglo de reglas de reescritura. En este, cada regla debe incluir lo siguiente:

    • Un source en el que se especifique la ruta que se va a usar para los Dynamic Links

      • A diferencia de las reglas que reescriben las rutas de acceso hacia las URL, las reglas de reescritura de Dynamic Links no pueden incluir expresiones regulares.
    • Un atributo dynamicLinks configurado como true

Configura encabezados

Opcional
Los encabezados permiten que tanto el cliente como el servidor pasen información adicional junto con una solicitud o respuesta. Algunos conjuntos de encabezados pueden afectar la manera en que el navegador controla la página y su contenido, incluido el control de acceso, la autenticación, el almacenamiento en caché y la codificación.

Crea un atributo headers que contenga un arreglo de objetos de encabezado para especificar encabezados de respuesta personalizados y específicos de un archivo. En cada objeto especifica un patrón de URL que active Hosting para aplicar los encabezados de respuesta personalizados que se especificaron (si coincide con la ruta de URL de la solicitud).

Este es un atributo headers de ejemplo:

"hosting": {
  // ...

  // Add the "headers" attribute within "hosting"
  "headers": [ {
    // Specifies a CORS header for all font files
    "source": "**/*.@(eot|otf|ttf|ttc|woff|font.css)",
    "headers": [ {
      "key": "Access-Control-Allow-Origin",
      "value": "*"
    } ]
  }, {
    // Overrides the default 1 hour browser cache with a 2 hour cache for all image files
    "source": "**/*.@(jpg|jpeg|gif|png)",
    "headers": [ {
      "key": "Cache-Control",
      "value": "max-age=7200"
    } ]
  }, {
    // A regular expression-based rewrite equivalent to the above behavior
    "regex": ".+/\w+\.(jpg|jpeg|gif|png)$",
    "headers": [ {
      "key": "Cache-Control",
      "value": "max-age=7200"
    } ]
  }, {
    // Sets the cache header for 404 pages to cache for 5 minutes
    "source": "404.html",
    "headers": [ {
      "key": "Cache-Control",
      "value": "max-age=300"
    } ]
  } ]
}

El atributo headers contiene un arreglo de definiciones. Cada una de ellas debe incluir lo siguiente:

  • source o regex: Especifica un patrón de URL que activa Hosting para aplicar el encabezado personalizado si coincide con la URL de la solicitud.

  • arreglo de (sub-)headers: Especifica los encabezados personalizados que Hosting aplica a la ruta de solicitud. Cada arreglo de subencabezado debe incluir un key y un value especificados.

Puedes obtener más información sobre Cache-Control en la sección de Hosting en la que se describen la entrega de contenido dinámico y el hosting de microservicios.

Además, puedes obtener más información sobre los encabezados CORS.

Controla las extensiones .html

Opcional
El atributo cleanUrls te permite controlar la inclusión de la extensión .html en las URL.

Si se configura como true, Hosting omite automáticamente la extensión .html de las URL de los archivos cargados. Si se agrega una extensión .html a la solicitud, Hosting realiza un redireccionamiento 301 hacia la misma ruta, pero elimina la extensión .html.

Puedes incluir un atributo cleanUrls en la sección hosting del archivo firebase.json para especificar la inclusión de extensiones .html. Por ejemplo:

"hosting": {
  // ...

  // Add the "cleanUrls" attribute within "hosting"
  "cleanUrls": true
}

Controla la inclusión de barras finales

Opcional
El atributo trailingSlash te permite controlar la inclusión de barras al final de las URL.

  • Si el valor es true, Hosting redireccionará las URL de modo que tengan una barra final.
  • Si el valor es false, Hosting redireccionará las URL de modo que no tengan una barra final.
  • Si no se especifica un valor, Hosting solo incluirá barras finales en los archivos de índice del directorio (p. ej., about/index.html).

Puedes incluir un atributo trailingSlash en la sección hosting del archivo firebase.json para especificar la inclusión de barras finales. Por ejemplo:

"hosting": {
  // ...

  // Add the "trailingSlash" attribute within "hosting"
  "trailingSlash": false
}

Concordancia de patrones glob

Las opciones de configuración de Firebase Hosting usan ampliamente la notación de concordancia de patrones glob con extglob, de manera similar a la forma en que Git maneja las reglas gitignore, y Bower maneja las reglas ignore. En esta página de wiki, se brinda una referencia más detallada. Sin embargo, aquí te ofrecemos una explicación de los ejemplos que se usaron en esta página:

  • firebase.json: Solo coincide con el archivo firebase.json ubicado en la raíz del directorio public.

  • **: Coincide con cualquier archivo o carpeta ubicado en un subdirectorio arbitrario.

  • *: Solo coincide con los archivos y las carpetas ubicadas en la raíz del directorio public.

  • **/.*: Coincide con cualquier archivo que comience con . (generalmente, estos son archivos ocultos, como la carpeta .git) ubicado en un subdirectorio arbitrario.

  • **/node_modules/**: Coincide con cualquier archivo o carpeta ubicado en un subdirectorio arbitrario de una carpeta node_modules, que puede estar en un subdirectorio arbitrario del directorio public.

  • **/*.@(jpg|jpeg|gif|png): Coincide con cualquier archivo ubicado en un subdirectorio arbitrario cuya terminación coincida exactamente con una de las siguientes extensiones: .jpg, .jpeg, .gif o .png.

Ejemplo completo de la configuración de Hosting

Este es un ejemplo completo de la configuración de firebase.json para Firebase Hosting. Ten en cuenta que un archivo firebase.json también puede contener configuraciones de otros servicios de Firebase.

{
  "hosting": {

    "public": "dist/app",  // "public" is the only required attribute for Hosting

    "ignore": [
      "firebase.json",
      "**/.*",
      "**/node_modules/**"
    ],

    "redirects": [ {
      "source": "/foo",
      "destination": "/bar",
      "type": 301
    }, {
      "source": "/firebase/**",
      "destination": "https://www.firebase.com",
      "type": 302
    } ],

    "rewrites": [ {
      // Shows the same content for multiple URLs
      "source": "/app/**",
      "destination": "/app/index.html"
    }, {
      // Configures a custom domain for Dynamic Links
      "source": "/promos/**",
      "dynamicLinks": true
    }, {
      // Directs a request to Cloud Functions
      "source": "/bigben",
      "function": "bigben"
    }, {
      // Directs a request to a Cloud Run containerized app
      "source": "/helloworld",
      "run": {
        "serviceId": "helloworld",
        "region": "us-central1"
      }
    } ],

    "headers": [ {
      "source": "**/*.@(eot|otf|ttf|ttc|woff|font.css)",
      "headers": [ {
        "key": "Access-Control-Allow-Origin",
        "value": "*"
      } ]
    }, {
      "source": "**/*.@(jpg|jpeg|gif|png)",
      "headers": [ {
        "key": "Cache-Control",
        "value": "max-age=7200"
      } ]
    }, {
      "source": "404.html",
      "headers": [ {
        "key": "Cache-Control",
        "value": "max-age=300"
      } ]
    } ],

    "cleanUrls": true,

    "trailingSlash": false

    // Required to configure custom domains for Dynamic Links
    "appAssociation": "AUTO",

  }
}