Com o Firebase Hosting, você pode configurar um comportamento de hospedagem personalizado para solicitações ao seu site.
O que você pode configurar para hospedagem?
Especifique quais arquivos no diretório local do projeto você deseja implantar no Firebase Hosting. Aprenda como.
Servir uma página 404/Not Found personalizada. Aprenda como.
Configure
redirects
para páginas que você moveu ou excluiu. Aprenda como.Configure
rewrites
para qualquer uma destas finalidades:Mostre o mesmo conteúdo para vários URLs. Aprenda como.
Execute uma função ou acesse um contêiner do Cloud Run a partir de um URL de hospedagem. Saiba como: função ou container .
Crie um link dinâmico de domínio personalizado. Aprenda como.
Adicione
headers
para transmitir informações adicionais sobre uma solicitação ou resposta, como como os navegadores devem lidar com a página e seu conteúdo (autenticação, cache, codificação, etc.). Aprenda como.Configure reescritas de internacionalização (i18n) para fornecer conteúdo específico com base na preferência de idioma e/ou país do usuário. Saiba como (página diferente).
Onde você define sua configuração de hospedagem?
Você define a configuração do Firebase Hosting no arquivo firebase.json
. O Firebase cria automaticamente seu arquivo firebase.json
na raiz do diretório do projeto quando você executa o comando firebase init
.
Você pode encontrar um exemplo completo de configuração firebase.json
(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 .
Você pode verificar o conteúdo firebase.json
implantado usando a API REST do Hosting .
Ordem de prioridade das respostas de hospedagem
Às vezes, as diferentes opções de configuração do Firebase Hosting descritas nesta página podem se sobrepor. Caso haja conflito, a Hosting determina sua resposta utilizando a seguinte ordem de prioridade:
- Namespaces reservados que começam com um segmento de caminho
/__/*
- Redirecionamentos configurados
- Conteúdo estático de correspondência exata
- Reescritas configuradas
- Página 404 personalizada
- Página 404 padrão
Se você estiver usando i18n rewrites , a correspondência exata e a ordem de prioridade de manipulação 404 serão expandidas em escopo para acomodar seu "conteúdo i18n".
Especifique quais arquivos implantar
Os atributos padrão – public
e ignore
– incluídos no arquivo firebase.json
padrão definem quais arquivos no diretório do seu projeto devem ser implantados no seu projeto do Firebase.
A configuração hosting
padrão em um arquivo firebase.json
é semelhante a esta:
"hosting": {
"public": "public", // the only required attribute for Hosting
"ignore": [
"firebase.json",
"**/.*",
"**/node_modules/**"
]
}
público
Obrigatório
O atributo public
especifica qual diretório implantar no Firebase Hosting. O valor padrão é um diretório chamado public
, mas você pode especificar qualquer caminho de diretório, desde que exista no diretório do seu projeto.
A seguir está o nome especificado padrão do diretório a ser implementado:
"hosting": {
"public": "public"
// ...
}
Você pode alterar o valor padrão para o diretório que deseja implementar:
"hosting": {
"public": "dist/app"
// ...
}
ignorar
Opcional
O atributo ignore
especifica os arquivos a serem ignorados na implantação. Pode receber globs da mesma forma que o Git trata .gitignore
.
A seguir estão os valores padrão para os arquivos ignorarem:
"hosting": {
// ...
"ignore": [
"firebase.json", // the Firebase configuration file (the file described on this page)
"**/.*", // files with a leading period should be hidden from the system
"**/node_modules/**" // contains dependencies used to create your site but not run it
]
}
Personalize uma página 404/Não encontrada
Opcional
Você pode exibir um erro 404 Not Found
personalizado quando um usuário tenta acessar uma página que não existe.
Crie um novo arquivo no diretório public
do seu projeto, nomeie-o 404.html
e adicione seu conteúdo 404 Not Found
personalizado ao arquivo.
O Firebase Hosting exibirá o conteúdo desta página 404.html
personalizada se um navegador acionar um erro 404 Not Found
em seu domínio ou subdomínio.
Configurar redirecionamentos
Opcional
Use um redirecionamento de URL para evitar links quebrados caso você tenha movido uma página ou para encurtar URLs. Por exemplo, você pode redirecionar um navegador de example.com/team
para example.com/about.html
.
Especifique redirecionamentos de URL criando um atributo redirects
que contém uma matriz de objetos (chamados de "regras de redirecionamento"). Em cada regra, especifique um padrão de URL que, se corresponder ao caminho do URL da solicitação, acionará o Hosting para responder com um redirecionamento para o URL de destino especificado.
Aqui está a estrutura básica para um atributo redirects
. Este exemplo redireciona solicitações para /foo
fazendo uma nova solicitação para /bar
.
"hosting": {
// ...
// Returns a permanent redirect to "/bar" for requests to "/foo" (but not "/foo/**")
"redirects": [ {
"source": "/foo",
"destination": "/bar",
"type": 301
} ]
}
"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
contém uma matriz de regras de redirecionamento, onde cada regra deve incluir os campos da tabela abaixo.
O Firebase Hosting compara o valor de source
ou regex
com todos os caminhos de URL no início de cada solicitação (antes que o navegador determine se existe um arquivo ou pasta nesse caminho). Se uma correspondência for encontrada, o servidor de origem do Firebase Hosting envia uma resposta de redirecionamento HTTPS informando ao navegador para fazer uma nova solicitação no URL destination
.
Campo | Descrição | |
---|---|---|
redirects | ||
source (recomendado)ou regex | Um padrão de URL que, se corresponder ao URL da solicitação inicial, aciona o Hosting para aplicar o redirecionamento
| |
destination | Uma URL estática onde o navegador deve fazer uma nova solicitação Este URL pode ser um caminho relativo ou absoluto. | |
type | O código de resposta HTTPS
|
Capture 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, em seguida, reutilizar esses segmentos no caminho destination
da regra.
Se estiver usando um campo source
(ou seja, especificando um glob para seu padrão de URL), você poderá capturar segmentos incluindo um prefixo :
para identificar o segmento. Se você também precisar capturar o caminho do URL restante após o segmento, inclua um *
imediatamente após o segmento. 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 } ] }
Se estiver usando um campo regex
(ou seja, especificando uma expressão regular RE2 para seu padrão de URL), você poderá capturar segmentos usando grupos de captura RE2 nomeados ou não. Grupos de captura nomeados podem ser usados no campo destination
com um prefixo :
, enquanto grupos de captura não nomeados podem ser referenciados por seu í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 reescritas
Opcional
Use uma reescrita para mostrar o mesmo conteúdo para vários URLs. As reescritas são particularmente úteis com correspondência de padrões, pois você pode aceitar qualquer URL que corresponda ao padrão e deixar o código do lado do cliente decidir o que exibir.
Você também pode usar reescritas para oferecer suporte a aplicativos que usam pushState HTML5 para navegação. Quando um navegador tenta abrir um caminho de URL que corresponda ao padrão de URL de source
ou regex
especificado, o navegador receberá o conteúdo do arquivo no URL destination
.
Especifique reescritas de URL criando um atributo rewrites
que contém uma matriz de objetos (chamadas "regras de reescrita"). Em cada regra, especifique um padrão de URL que, se corresponder ao caminho do URL da solicitação, acionará o Hosting para responder como se o serviço tivesse recebido o URL de destino especificado.
Aqui está a estrutura básica para um atributo rewrites
. Este exemplo serve index.html
para solicitações de arquivos ou diretórios que não existem.
"hosting": {
// ...
// Serves index.html for requests to files or directories that do not exist
"rewrites": [ {
"source": "**",
"destination": "/index.html"
} ]
}
"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
contém uma matriz de regras de reescrita, onde cada regra deve incluir os campos da tabela abaixo.
O Firebase Hosting só aplica uma regra de reescrita se não existir um arquivo ou diretório em um caminho de URL que corresponda à source
especificada ou ao padrão de URL regex
. Quando uma solicitação aciona uma regra de reescrita, o navegador retorna o conteúdo real do arquivo destination
especificado em vez de um redirecionamento HTTP.
Campo | Descrição | |
---|---|---|
rewrites | ||
source (recomendado)ou regex | Um padrão de URL que, se corresponder ao URL da solicitação inicial, aciona o Hosting para aplicar a reescrita
| |
destination | Um arquivo local que deve existir Este URL pode ser um caminho relativo ou absoluto. |
Solicitações diretas para uma função
Você pode usar rewrites
para servir uma função de um URL do Firebase Hosting. O exemplo a seguir é um trecho da veiculação de conteúdo dinâmico usando o Cloud Functions .
Por exemplo, para direcionar todas as solicitações da página /bigben
no seu site de hospedagem para executar a função bigben
:
"hosting": {
// ...
// Directs all requests from the page `/bigben` to execute the `bigben` function
"rewrites": [ {
"source": "/bigben",
"function": {
"functionId": "bigben",
"region": "us-central1" // optional (see note below)
"pinTag": true // optional (see note below)
}
} ]
}
Se
region
for omitida de um blocofunction
da configuraçãohosting.rewrites
, a CLI do Firebase tentará detectar automaticamente a região a partir do código-fonte da função que, se não for especificado, será padronizado comous-central1
. Se o código-fonte da função não estiver disponível, a CLI tentará detectar a região da função implementada. Se a função estiver em várias regiões, a CLI exigirá queregion
seja especificada na configuraçãohosting.rewrites
.
O recurso
pinTag
está disponível apenas no Cloud Functions para Firebase (2ª geração). Com esse recurso, você pode garantir que cada função de geração de conteúdo dinâmico do seu site seja mantida sincronizada com seus recursos estáticos de hospedagem e configuração de hospedagem. Além disso, esse recurso permite que você visualize suas reescritas para funções nos canais de visualização do Hosting.Se você adicionar
"pinTag": true
a um blocofunction
da configuraçãohosting.rewrites
, a função "fixada" será implantada junto com seus recursos e configuração estáticos do Hosting, mesmo ao executar. Se você reverter uma versão do seu site, a função "fixada" também será revertida.
firebase deploy --only hosting Esse recurso depende de tags do Cloud Run , que têm um limite de 1.000 tags por serviço e 2.000 tags por região. Isso significa que após centenas de implantações, as versões mais antigas de um site podem parar de funcionar.
Depois de adicionar esta regra de reescrita e implantar no Firebase (usando firebase deploy
), sua função poderá ser acessada por meio dos seguintes URLs:
Seus subdomínios do Firebase:
PROJECT_ID .web.app/bigben
ePROJECT_ID .firebaseapp.com/bigben
Quaisquer domínios personalizados conectados:
CUSTOM_DOMAIN /bigben
Ao redirecionar solicitações para funções com Hosting, os métodos de solicitação HTTP suportados são GET
, POST
, HEAD
, PUT
, DELETE
, PATCH
e OPTIONS
. Outros métodos como REPORT
ou PROFIND
não são suportados.
Solicitações diretas para um contêiner do Cloud Run
Você pode 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 veiculação de conteúdo dinâmico usando o Cloud Run .
Por exemplo, para direcionar todas as solicitações da página /helloworld
em seu site de hospedagem para acionar a inicialização e a execução de uma instância de contêiner helloworld
:
"hosting": {
// ...
// Directs all requests from the page `/helloworld` to trigger and run a `helloworld` container
"rewrites": [ {
"source": "/helloworld",
"run": {
"serviceId": "helloworld", // "service name" (from when you deployed the container image)
"region": "us-central1" // optional (if omitted, default is us-central1)
}
} ]
}
Com esse recurso, você pode garantir que a revisão do serviço Cloud Run para gerar o conteúdo dinâmico do seu site seja mantida sincronizada com os recursos estáticos do Hosting e a configuração do Hosting. Além disso, esse recurso permite que você visualize suas reescritas nos canais de visualização do Cloud Run no Hosting.
Se você adicionar
"pingTag": true
a um blocorun
da configuração dohosting.rewrites
, seus recursos e configurações estáticas do Hosting serão fixados na revisão mais recente do serviço Cloud Run, no momento da implantação. Se você reverter uma versão do seu site, a revisão do serviço Cloud Run "fixado" também será revertida.Esse recurso depende de tags do Cloud Run , que têm um limite de 1.000 tags por serviço e 2.000 tags por região. Isso significa que após centenas de implantações, as versões mais antigas de um site podem parar de funcionar.
Depois de adicionar esta regra de reescrita e implantar no Firebase (usando firebase deploy
), sua imagem de contêiner poderá ser acessada por meio dos seguintes URLs:
Seus subdomínios do Firebase:
PROJECT_ID .web.app/helloworld
ePROJECT_ID .firebaseapp.com/helloworld
Quaisquer domínios personalizados conectados:
CUSTOM_DOMAIN /helloworld
Ao redirecionar solicitações para contêineres do Cloud Run com Hosting, os métodos de solicitação HTTP compatíveis são GET
, POST
, HEAD
, PUT
, DELETE
, PATCH
e OPTIONS
. Outros métodos como REPORT
ou PROFIND
não são suportados.
Para obter o melhor desempenho, coloque seu serviço Cloud Run com hospedagem usando as seguintes regiões:
-
us-west1
-
us-central1
-
us-east1
-
europe-west1
-
asia-east1
As reescritas no Cloud Run a partir do Hosting são compatíveis com as seguintes regiões:
-
asia-east1
-
asia-east2
-
asia-northeast1
-
asia-northeast2
-
asia-northeast3
-
asia-south1
-
asia-south2
-
asia-southeast1
-
asia-southeast2
-
australia-southeast1
-
australia-southeast2
-
europe-central2
-
europe-north1
-
europe-southwest1
-
europe-west1
-
europe-west12
-
europe-west2
-
europe-west3
-
europe-west4
-
europe-west6
-
europe-west8
-
europe-west9
-
me-central1
-
me-west1
-
northamerica-northeast1
-
northamerica-northeast2
-
southamerica-east1
-
southamerica-west1
-
us-central1
-
us-east1
-
us-east4
-
us-east5
-
us-south1
-
us-west1
-
us-west2
-
us-west3
-
us-west4
-
us-west1
-
us-central1
-
us-east1
-
europe-west1
-
asia-east1
Crie links dinâmicos de domínio personalizado
Você pode usar rewrites
para criar Dynamic Links de domínio personalizado. Visite a documentação do Dynamic Links para obter informações detalhadas sobre como configurar um domínio personalizado para Dynamic Links .
Use seu domínio personalizado apenas para links dinâmicos
"hosting": { // ... "appAssociation": "AUTO", // required for Dynamic Links (default is AUTO if not specified) // Add the "rewrites" attribute within "hosting" "rewrites": [ { "source": "/**", // the Dynamic Links start with "https://CUSTOM_DOMAIN/" "dynamicLinks": true } ] }
Especifique prefixos de caminho de domínio personalizados para usar em Dynamic Links
"hosting": { // ... "appAssociation": "AUTO", // required for Dynamic Links (default is AUTO if not specified) // Add the "rewrites" attribute within "hosting" "rewrites": [ { "source": "/promos/**", // the Dynamic Links start with "https://CUSTOM_DOMAIN/promos/" "dynamicLinks": true }, { "source": "/links/share/**", // the Dynamic Links start with "https://CUSTOM_DOMAIN/links/share/" "dynamicLinks": true } ] }
A configuração de links dinâmicos no arquivo firebase.json
requer o seguinte:
Campo | Descrição | |
---|---|---|
appAssociation | Deve ser definido como
| |
rewrites | ||
source | Um caminho que você deseja usar para links dinâmicos Ao contrário das regras que reescrevem caminhos para URLs, as regras de reescrita para links dinâmicos não podem conter expressões regulares. | |
dynamicLinks | Deve ser 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 resposta. Alguns conjuntos de cabeçalhos podem afetar a forma como o navegador lida com a página e seu conteúdo, incluindo controle de acesso, autenticação, cache e codificação.
Especifique cabeçalhos de resposta personalizados e específicos do arquivo criando um atributo headers
que contém uma matriz de objetos de cabeçalho. Em cada objeto, especifique um padrão de URL que, se corresponder ao caminho do URL da solicitação, acionará o Hosting para aplicar os cabeçalhos de resposta personalizados especificados.
Aqui está a estrutura básica para um atributo headers
. Este exemplo aplica um cabeçalho CORS para todos os arquivos de fonte.
"hosting": {
// ...
// Applies a CORS header for all font files
"headers": [ {
"source": "**/*.@(eot|otf|ttf|ttc|woff|font.css)",
"headers": [ {
"key": "Access-Control-Allow-Origin",
"value": "*"
} ]
} ]
}
"hosting": { // ... // Add the "headers" attribute within "hosting" "headers": [ { // Applies 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
contém uma matriz de definições, onde cada definição deve incluir os campos da tabela abaixo.
Campo | Descrição | ||
---|---|---|---|
headers | |||
source (recomendado)ou regex | Um padrão de URL que, se corresponder ao URL da solicitação inicial, aciona o Hosting para aplicar o cabeçalho personalizado
Para criar um cabeçalho que corresponda à sua página 404 personalizada , use | ||
matriz de (sub) headers | Os cabeçalhos personalizados que o Hosting aplica ao caminho da solicitação Cada subcabeçalho deve incluir um par | ||
key | O nome do cabeçalho, por exemplo Cache-Control | ||
value | O valor do cabeçalho, por exemplo max-age=7200 |
Você pode aprender mais sobre Cache-Control
na seção Hospedagem que descreve o fornecimento de conteúdo dinâmico e hospedagem de microsserviços. Você também pode aprender mais sobre cabeçalhos CORS .
Controlar extensões .html
Opcional
O atributo cleanUrls
permite controlar se os URLs devem ou não incluir a extensão .html
.
Quando true
, o Hosting descarta automaticamente a extensão .html
dos URLs dos arquivos enviados. Se uma extensão .html
for adicionada na solicitação, o Hosting realiza um redirecionamento 301
para o mesmo caminho, mas elimina a extensão .html
.
Veja como controlar a inclusão de .html
em URLs incluindo um atributo cleanUrls
:
"hosting": {
// ...
// Drops `.html` from uploaded URLs
"cleanUrls": true
}
Controlar barras finais
Opcional
O atributo trailingSlash
permite controlar se URLs de conteúdo estático devem ou não incluir barras finais.
- Quando
true
, o Hosting redireciona os URLs para adicionar uma barra final. - Quando
false
, o Hosting redireciona URLs para remover uma barra final. - Quando não especificado, o Hosting usa apenas barras finais para arquivos de índice de diretório (por exemplo,
about/index.html
).
Veja como controlar barras finais adicionando um atributo trailingSlash
:
"hosting": {
// ...
// Removes trailing slashes from URLs
"trailingSlash": false
}
O atributo trailingSlash
não afeta reescritas em conteúdo dinâmico veiculado pelo Cloud Functions ou Cloud Run.
Correspondência de padrão 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 à forma como o Git lida com regras gitignore
e o Bower lida com regras ignore
. Esta página wiki é uma referência mais detalhada, mas a seguir estão explicações de exemplos usados nesta página:
firebase.json
— Corresponde apenas ao arquivofirebase.json
na raiz do diretóriopublic
**
— Corresponde a qualquer arquivo ou pasta em um subdiretório arbitrário*
— Corresponde apenas a arquivos e pastas na raiz do diretóriopublic
**/.*
— Corresponde a qualquer arquivo que comece com.
(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 pastanode_modules
, que pode estar em um subdiretório arbitrário do diretóriopublic
**/*.@(jpg|jpeg|gif|png)
— Corresponde a qualquer arquivo em um subdiretório arbitrário que termine exatamente com um dos seguintes:.jpg
,.jpeg
,.gif
ou.png
Exemplo de configuração completa de hospedagem
Veja a seguir um exemplo completo de configuração 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",
}
}