Ir a la consola

Configura el comportamiento del hosting

Firebase Hosting te permite configurar comportamientos de hosting personalizados, como páginas de error personalizadas, redireccionamientos, reescrituras y encabezados. Además, permite especificar qué archivos implementar del directorio del proyecto al 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 de tu 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 coincidencia exacta
  4. Reescrituras configuradas
  5. Página 404 personalizada
  6. Página 404 predeterminada

Especifica qué archivos se deben implementar

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

La configuración predeterminada de hosting en el archivo firebase.json se ve así:

"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 de tu proyecto.

A continuación, se presenta 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 ignorar en la implementación. Puede usar el patrón glob de la misma manera en que Git controla .gitignore.

Los valores predeterminados de los archivos que se deben ignorar son los siguientes:

"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/no encontrada

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

Crea un archivo nuevo en el directorio public de tu 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 tu dominio o subdominio.

Configura redireccionamientos

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

Para especificar el redireccionamiento de URL, incluye un atributo redirects dentro de hosting en tu archivo firebase.json. Por 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
  } ]
}

El atributo redirects contiene un arreglo de reglas de redireccionamiento. En este, cada regla debe incluir lo siguiente:

  • Un source que especifique un patrón glob

  • Un destination, este es una URL estática que puede ser una ruta absoluta o relacionada

  • Un type que especifique el código de respuesta HTTP

Firebase Hosting compara el valor source 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 la ruta). Si aparece una coincidencia, el servidor de origen de Firebase Hosting enviará una respuesta de redireccionamiento HTTP que indicará al navegador que debe realizar una solicitud nueva en la URL destination.

Por último, el valor type indica el código de respuesta HTTP específico que se proporciona y puede ser 301 para “Movido de forma permanente” o 302 para “Encontrado” (redireccionamiento temporal).

Captura segmentos de URL para los redireccionamientos

Opcional
En ocasiones, es posible que tengas que capturar segmentos específicos de una URL source de redireccionamiento y, luego, volver a utilizarlos en la URL destination de redireccionamiento.

Para capturar estos segmentos, identifícalos con el prefijo :. Además, 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 caputured by the "source" value
    "type": 301
  } ]
}

Configura reescrituras

Opcional
Usa una reescritura para mostrar el mismo contenido en varias URL. Las reescrituras son especialmente útiles con la comparación 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 intenta abrir una URL source específica, se le proporcionará el contenido del archivo que se encuentra en la URL destination.

Incluye un atributo rewrites dentro de hosting en tu archivo firebase.json para especificar reescrituras de URL. Por 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"
  }, {
    // Excludes specified pathways from rewrites
    "source": "!/@(js|css)/**",
    "destination": "/index.html"
  } ]
}

El atributo rewrites contiene un arreglo de reglas de reescritura. En este, cada regla debe incluir lo siguiente:

  • Un source que especifique un patrón glob

  • Un destination, este debe ser un archivo local existente

Firebase Hosting solo aplicará una regla de reescritura en el caso de que el source especificado no contenga un archivo o directorio. Cuando se activa una regla, 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 Entrega contenido dinámico con Cloud Functions.

Por ejemplo, para dirigir todas las solicitudes desde la página /bigben en el sitio de Hosting a fin de ejecutar la función bigben:

"hosting": {
  // ...

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

Después de agregar esta regla de reescritura y de la implementación a Firebase (mediante firebase deploy), se puede 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 Entrega contenido dinámico con Cloud Run.

Por ejemplo, para dirigir todas las solicitudes desde la página /helloworld de tu sitio de Hosting a fin de activar el inicio y la ejecución de una instancia de contenedor de helloworld:

"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 la implementación a Firebase (mediante firebase deploy), se puede acceder a la imagen del 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 prefjios 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 tu 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.json y apple-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.

Incluye un atributo headers dentro de hosting en tu archivo firebase.json para especificar encabezados de respuesta personalizados y específicos de un archivo. Por 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"
    } ]
  }, {
    // 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. En este, cada definición debe incluir lo siguiente:

  • Un valor source que Hosting compara con la ruta de la solicitud original, independientemente de las reglas de reescritura existentes.

  • Un arreglo de (sub-)headers que Hosting aplica en la ruta de la solicitud, cada arreglo de subencabezado debe incluir una key y un value especificados.

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

Adicionalmente, obtén 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 ignora 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.

Especifica la inclusión de extensiones .html. Para ello, incluye un atributo cleanUrls dentro de hosting en tu archivo firebase.json. 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 dentro de hosting en tu archivo firebase.json para especificar la inclusión de barras finales. Por ejemplo:

"hosting": {
  // ...

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

Comparación de patrones glob

Las opciones de configuración de Firebase Hosting usan ampliamente la notación de comparación 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 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 archivos y carpetas en la raíz del directorio public.

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

  • **/node_modules/** coincide con cualquier archivo o carpeta en un subdirectorio arbitrario de la carpeta node_modules, que puede ubicarse 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

A continuación, se presenta 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",

  }
}