Configurar o comportamento de hospedagem

Com o Firebase Hosting, é possível configurar um comportamento de hospedagem personalizado, incluindo páginas de erro, redirecionamentos, substituições e cabeçalhos personalizados. Também é possível especificar quais arquivos implantar do diretório para o projeto do Firebase.

Defina a configuração do Firebase Hosting no seu arquivo firebase.json.

Encontre seu arquivo firebase.json na raiz do diretório do seu projeto. O Firebase cria automaticamente seu arquivo firebase.json quando o comando firebase init for executado.

É possível encontrar um exemplo de configuração firebase.json completo (abrangendo apenas o Firebase Hosting) na parte inferior desta página. Observe que um arquivo firebase.json também pode conter configurações para outros serviços do Firebase.

É possível verificar o conteúdo firebase.json implementado usando a API REST do Hosting.

Ordem de prioridade das respostas do Hosting

As diferentes opções de configuração do Firebase Hosting descritas nesta página podem, às vezes, se sobrepor. Se houver um conflito, o Hosting determinará sua resposta usando a seguinte ordem de prioridade:

  1. Namespaces reservados que começam com um segmento de caminho /__/*
  2. Redirecionamentos configurados
  3. Conteúdo estático de correspondência exata
  4. Substituições configuradas
  5. Página 404 personalizada
  6. Página 404 padrão

Especificar os arquivos a serem implantados

Os atributos padrão, public e ignore, incluídos no arquivo firebase.json padrão, definem quais arquivos no diretório do projeto devem ser implantados no projeto do Firebase.

A configuração hosting padrão em um arquivo firebase.json será semelhante ao abaixo:

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

public

Obrigatório
O atributo public especifica qual diretório será implantado no Firebase Hosting. O valor padrão é um diretório chamado public, mas é possível especificar o caminho de qualquer diretório, contanto que ele exista no diretório do seu projeto.

Veja abaixo o nome especificado padrão do diretório a ser implantado:

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

  // ...
}

É possível alterar o valor padrão para o diretório que você quer implantar:

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

  // ...
}

ignore

Opcional
O atributo ignore especifica os arquivos a serem ignorados na implantação. Ele pode usar globs da mesma forma que o sistema Git (em inglês) faz com o .gitignore.

Veja abaixo os valores padrão dos arquivos a serem ignorados:

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

Personalizar uma página 404/não encontrada

Opcional
Você pode exibir um erro 404 Not Found personalizado quando um usuário tentar acessar uma página que não existe.

Criar um novo arquivo no diretório public do projeto, nomeie-o como 404.html e adicione o conteúdo 404 Not Found personalizado para o arquivo.

O Firebase Hosting exibirá o conteúdo desse 404.html personalizado se um navegador acionar um erro 404 Not Found no seu domínio ou subdomínio.

Configurar redirecionamentos

Opcional
Use um redirecionamento de URL para evitar links corrompidos se você tiver movido uma página ou para encurtar URLs. Por exemplo, você pode redirecionar um navegador de example.com/team para example.com/about.html.

Se for preciso especificar redirecionamentos de URL, crie um atributo redirects que contenha uma matriz de objetos (chamada de "regras de redirecionamento"). Em cada regra, especifique um padrão de URL que aciona o Hosting para responder com um redirecionamento ao destino especificado em caso de correspondência com o caminho do URL da solicitação.

Veja um exemplo do atributo redirects:

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

O atributo redirects tem uma matriz de regras de redirecionamento onde todas precisam conter os seguintes campos:

  • source ou regex: especifica um padrão de URL que aciona o Hosting para aplicar o redirecionamento em caso de correspondência com o URL da solicitação.

  • destination: especifica um URL estático que pode ser um caminho relativo ou absoluto

  • type: especifica o código de resposta HTTP

    • Use o tipo 301 para "Movido permanentemente".
    • Use o tipo 302 para "Encontrado" (redirecionamento temporário).

O Firebase Hosting compara o valor source ou regex com todos os caminhos de URL no início de cada solicitação antes de o navegador determinar se um arquivo ou uma pasta existe nesse caminho. Se uma correspondência for encontrada, o servidor de origem do Firebase Hosting enviará uma resposta de redirecionamento HTTP informando ao navegador que é necessário fazer uma nova solicitação no URL destination.

Capturar segmentos de URL para redirecionamentos

Opcional
Às vezes, pode ser necessário capturar segmentos específicos do padrão de URL de uma regra de redirecionamento (valor source ou regex) e depois reutilizá-los no caminho destination da regra.

Capturar segmentos de URL ao usar globs

Se você estiver usando um campo source, ou seja, especificando um glob para seu padrão de URL, poderá capturar segmentos. Basta incluir um prefixo : para identificar o item que deve ser capturado. Caso também precise fazer isso com o caminho de URL restante após o segmento, inclua um * diretamente nessa posição. Por exemplo:

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

Capturar segmentos de URL ao usar expressões regulares RE2

Se você estiver usando um campo regex, ou seja, especificando uma expressão regular RE2 para seu padrão de URL, poderá capturar segmentos. Basta usar grupos de captura RE2 nomeados ou não. Os grupos de captura nomeados podem ser usados no campo destination com um prefixo :. Os não nomeados podem ser referenciados pelo índice numérico no valor regex, indexado a partir de 1. Por exemplo:

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

Configurar substituições

Opcional
Use uma substituição para mostrar o mesmo conteúdo para vários URLs. Essa função é particularmente útil com a correspondência de padrões, já que é possível aceitar qualquer URL que corresponda ao padrão e deixar que o código do cliente decida o que exibir.

As substituições também podem ser usadas para oferecer compatibilidade com apps que usam HTML5 pushState (em inglês) para navegação. Quando um navegador tenta abrir um caminho de URL que corresponde ao padrão de URL source ou regex especificado, o navegador recebe o conteúdo do arquivo no URL destination.

Para especificar substituições de URL, crie um atributo rewrites que contenha uma matriz de objetos (chamada de "regras de substituição"). Em cada regra, especifique um padrão de URL que, em caso de correspondência com o caminho do URL da solicitação, aciona o Hosting para responder como se o serviço tivesse recebido o URL de destino especificado.

Veja um exemplo do atributo rewrites:

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

O atributo rewrites tem uma matriz de regras de substituição onde todas precisam conter os seguintes campos:

  • source ou regex: especifica um padrão de URL que aciona o Hosting para aplicar a regravação em caso de correspondência com o URL da solicitação.

  • destination: especifica um arquivo local que precisa existir.

O Firebase Hosting só aplicará uma regra de substituição se um arquivo ou diretório não existir em um caminho de URL que corresponda ao padrão de URL source ou regex especificado. Quando uma regra de substituição é acionada, o navegador retorna o conteúdo real do arquivo destination especificado em vez de um redirecionamento HTTP.

Solicitações diretas para uma função

É possível usar rewrites para exibir uma função de um URL do Firebase Hosting. O exemplo a seguir é um trecho da exibição de conteúdo dinâmico usando o Cloud Functions.

Por exemplo, caso queira direcionar todas as solicitações da página /bigben no site do Hosting para executar a função bigben:

"hosting": {
  // ...

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

Depois de adicionar esta regra de substituição e implantar no Firebase (usando firebase deploy), a função pode ser acessada pelos seguintes URLs:

  • Subdomínios do Firebase: projectID.web.app/bigben e projectID.firebaseapp.com/bigben

  • Qualquer domínio personalizado conectado: custom-domain/bigben

Solicitações diretas para um contêiner do Cloud Run

É possível usar rewrites para acessar um contêiner do Cloud Run a partir de um URL do Firebase Hosting. O exemplo a seguir é um trecho da exibição de conteúdo dinâmico usando o Cloud Run.

Por exemplo, para direcionar todas as solicitações da página /helloworld no site do Hosting para acionar a inicialização e execução de um instância de contêiner 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)
   }
 } ]
}

Depois de adicionar esta regra de substituição e implantar no Firebase (usando firebase deploy), sua imagem de contêiner pode ser acessada pelos seguintes URLs:

  • Subdomínios do Firebase: projectID.web.app/helloworld e projectID.firebaseapp.com/helloworld

  • Qualquer domínio personalizado conectado: custom-domain/helloworld

É possível usar rewrites para criar Dynamic Links de domínio personalizado. Acesse a documentação do Dynamic Links para receber informações detalhadas sobre a configuração de um domínio personalizado para Dynamic Links.

Por exemplo:

  • Use seu domínio apenas 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
      } ]
    }
    
  • Especifique os prefixos de caminho que você quer usar para o 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
      } ]
    }
    

Veja a seguir os requisitos para a configuração do Dynamic Links no arquivo firebase.json:

  • Um atributo appAssociation definido como AUTO.

    • O padrão para appAssociation é AUTO se você não incluir o atributo na sua configuração.
    • Com esse atributo definido como AUTO, o Hosting gera dinamicamente os arquivos assetlinks.json e apple-app-site-association quando eles são solicitados.
  • Um atributo rewrites para Dynamic Links que contém uma matriz de regras de substituição, em que cada regra deve incluir:

    • Um source especificando um caminho que você quer usar para o Dynamic Links

      • Ao contrário das regras que substituem caminhos por URLs, as regras de substituição do Dynamic Links não podem conter expressões regulares.
    • Um atributo dynamicLinks definido como true

Configurar cabeçalhos

Opcional
Os cabeçalhos permitem que o cliente e o servidor passem informações adicionais junto com uma solicitação ou uma resposta. Alguns conjuntos de cabeçalhos podem afetar como o navegador lida com a página e o conteúdo dela, incluindo controle de acesso, autenticação, armazenamento em cache e codificação.

Crie um atributo headers que contenha uma matriz de objetos de cabeçalho para especificar cabeçalhos de resposta personalizados e específicos do arquivo. Em cada objeto, especifique um padrão de URL que aciona o Hosting para aplicar os cabeçalhos de resposta personalizados especificados em caso de correspondência com o caminho do URL da solicitação.

Veja um exemplo do atributo headers:

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

O atributo headers tem uma matriz de definições onde todas precisam conter os seguintes campos:

  • source ou regex: especifica um padrão de URL que aciona o Hosting para aplicar o cabeçalho personalizado em caso de correspondência com o URL da solicitação.

  • Matriz de (sub)headers: especifica os cabeçalhos personalizados que o Hosting aplica ao caminho da solicitação. Cada matriz de subcabeçalho precisa incluir key e value especificados.

Saiba mais sobre Cache-Control na seção de Hosting que descreve a exibição de conteúdo dinâmico e hospedagem de microsserviços.

Também é possível saber mais sobre os cabeçalhos CORS.

Controlar extensões .html

Opcional
O atributo cleanUrls permite que você controle se os URLs devem ou não incluir a extensão .html.

Quando true, o Hosting descarta automaticamente a extensão .html dos URLs de arquivos enviados. Se uma extensão .html for adicionada na solicitação, o Hosting executará um redirecionamento 301 para o mesmo caminho, mas eliminará a extensão .html.

Especifique a inclusão de extensões .html ao incluir um atributo cleanUrls em hosting em seu arquivo firebase.json. Por exemplo:

"hosting": {
  // ...

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

Controlar barras finais

Opcional
O atributo trailingSlash permite que você controle se os URLs precisam incluir barras finais.

  • Quando true, o Hosting redireciona URLs para adicionar uma barra final.
  • Quando false, o Hosting redireciona URLs para remover uma barra final.
  • Quando não especificado, o Hosting usa barras finais somente para arquivos de índice de diretório (por exemplo, about/index.html).

Especifique a inclusão de barras finais incluindo um atributo trailingSlash em hosting em seu arquivo firebase.json. Por exemplo:

"hosting": {
  // ...

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

Correspondência de padrões glob

As opções de configuração do Firebase Hosting fazem uso extensivo da notação de correspondência de padrão glob com extglob, semelhante a como o Git manipula as regras gitignore e o Bower manipula as regras ignore. Esta página da wiki é uma referência mais detalhada, mas as seguintes são explicações dos exemplos usados nesta página:

  • firebase.json: corresponde apenas ao arquivo firebase.json na raiz do diretório public

  • **: corresponde a qualquer arquivo ou pasta em um subdiretório arbitrário

  • * corresponde apenas a arquivos e pastas na raiz do diretório public

  • **/.*: corresponde a qualquer arquivo iniciado por . (geralmente arquivos ocultos, como na pasta .git) em um subdiretório arbitrário

  • **/node_modules/**: corresponde a qualquer arquivo ou pasta em um subdiretório arbitrário de uma pasta node_modules, que pode estar em um subdiretório arbitrário do diretório public

  • **/*.@(jpg|jpeg|gif|png): corresponde a qualquer arquivo em um subdiretório arbitrário que termine com exatamente uma das seguintes opções: .jpg, .jpeg, .gif ou .png

Exemplo de configuração completa do Hosting

Veja a seguir um exemplo de configuração completo de firebase.json para o Firebase Hosting. Observe que um arquivo firebase.json também pode conter configurações para outros serviços do 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",

  }
}