С помощью Firebase Hosting вы можете настроить индивидуальное поведение хостинга для запросов к вашему сайту.
Что можно настроить для Hosting ?
Укажите, какие файлы из локального каталога проекта вы хотите развернуть на Firebase Hosting . Узнайте, как это сделать.
Создайте персонализированную страницу 404/Не найдено. Узнайте, как это сделать.
Настройте
redirectsдля страниц, которые вы переместили или удалили. Узнайте, как это сделать.Настройте
rewritesдля любой из этих целей:Показывать один и тот же контент для нескольких URL-адресов. Узнайте, как это сделать.
Выполняйте функцию или обращайтесь к контейнеру Cloud Run с URL-адреса Hosting . Узнайте, как: функция или контейнер .
Создайте собственный домен Dynamic Link . Узнайте, как это сделать.
Добавьте
headersдля передачи дополнительной информации о запросе или ответе, например, о том, как браузеры должны обрабатывать страницу и её содержимое (аутентификация, кэширование, кодирование и т. д.). Узнайте, как это сделать.Настройте интернационализацию (i18n) для отображения определённого контента в зависимости от языковых предпочтений и/или страны пользователя. Узнайте, как это сделать (на другой странице).
Где вы определяете конфигурацию Hosting ?
Конфигурация Firebase Hosting определяется в файле firebase.json . Firebase автоматически создаёт файл firebase.json в корне каталога вашего проекта при запуске команды firebase init .
Полный пример конфигурации firebase.json (относящийся только к Firebase Hosting ) можно найти внизу этой страницы. Обратите внимание, что файл firebase.json также может содержать конфигурации для других сервисов Firebase .
Вы можете проверить развернутое содержимое firebase.json с помощью Hosting REST API .
Приоритетный порядок ответов Hosting
Различные параметры конфигурации Firebase Hosting , описанные на этой странице, иногда могут пересекаться. В случае конфликта Hosting определяет свой ответ, используя следующий порядок приоритетов:
- Зарезервированные пространства имен, начинающиеся с сегмента пути
/__/* - Настроенные перенаправления
- Статический контент с точным соответствием
- Настроенные перезаписи
- Пользовательская страница 404
- Страница 404 по умолчанию
Если вы используете i18n-перезаписи , порядок приоритета точного соответствия и обработки 404 расширяется, чтобы учесть ваш «i18n-контент».
Укажите, какие файлы следует развернуть
Атрибуты по умолчанию — public и ignore — включенные в файл firebase.json по умолчанию, определяют, какие файлы в каталоге вашего проекта должны быть развернуты в вашем проекте Firebase.
Конфигурация hosting по умолчанию в файле firebase.json выглядит следующим образом:
"hosting": {
"public": "public", // the only required attribute for Hosting
"ignore": [
"firebase.json",
"**/.*",
"**/node_modules/**"
]
}
публичный
Необходимый
Атрибут public указывает, какой каталог следует развернуть на Firebase Hosting . Значение по умолчанию — каталог с именем public , но вы можете указать путь к любому каталогу, если он существует в каталоге вашего проекта.
Ниже приведено имя каталога для развертывания, заданное по умолчанию:
"hosting": {
"public": "public"
// ...
}
Вы можете изменить значение по умолчанию на каталог, который вы хотите развернуть:
"hosting": {
"public": "dist/app"
// ...
}
игнорировать
Необязательный
Атрибут ignore указывает файлы, которые следует игнорировать при развёртывании. Он может принимать подстановочные значения так же, как Git обрабатывает .gitignore .
Ниже приведены значения по умолчанию для файлов, которые следует игнорировать:
"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
]
}
Настройте страницу 404/Не найдено
Необязательный
Вы можете отображать пользовательскую ошибку 404 Not Found , когда пользователь пытается получить доступ к несуществующей странице.
Создайте новый файл в public каталоге вашего проекта, назовите его 404.html , затем добавьте в файл свой собственный контент 404 Not Found .
Firebase Hosting отобразит содержимое этой пользовательской страницы 404.html , если браузер вызовет ошибку 404 Not Found на вашем домене или поддомене.
Настроить перенаправления
Необязательный
Используйте перенаправление URL, чтобы предотвратить появление неработающих ссылок при перемещении страницы или сократить URL-адреса. Например, можно перенаправить браузер с example.com/team на example.com/about.html .
Укажите перенаправления URL, создав атрибут redirects , содержащий массив объектов (так называемые «правила перенаправления»). В каждом правиле укажите шаблон URL, который, при совпадении с путём URL запроса, запустит Hosting на указанный целевой URL.
Вот базовая структура атрибута redirects . В этом примере запросы перенаправляются на /foo путём создания нового запроса на /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
} ]
}
Атрибут redirects содержит массив правил перенаправления, где каждое правило должно включать поля из таблицы ниже.
Firebase Hosting сравнивает source значение или значение regex со всеми URL-путями в начале каждого запроса (до того, как браузер определит, существует ли файл или папка по этому пути). Если совпадение обнаружено, исходный сервер Firebase Hosting отправляет HTTPS-ответ с перенаправлением, сообщая браузеру о необходимости выполнить новый запрос по destination URL.
| Поле | Описание | |
|---|---|---|
redirects | ||
source (рекомендуется)или regex | Шаблон URL, который, если совпадает с URL-адресом исходного запроса, заставляет Hosting применять перенаправление.
| |
destination | Статический URL-адрес, по которому браузер должен сделать новый запрос. Этот URL может быть относительным или абсолютным путем. | |
type | Код ответа HTTPS
| |
Захват сегментов URL для перенаправлений
Необязательный
Иногда может потребоваться захватить определенные сегменты шаблона URL-адреса правила перенаправления ( source или значение regex ), а затем повторно использовать эти сегменты в destination пути правила.
Если вы используете поле source (то есть указываете глоб для шаблона URL), вы можете захватить сегменты, добавив префикс : для идентификации сегмента. Если вам также нужно захватить оставшийся путь URL после сегмента, добавьте * сразу после сегмента. Например:
"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 } ] }
Если вы используете поле regex (то есть указываете регулярное выражение RE2 для шаблона URL), вы можете захватывать сегменты, используя как именованные, так и неименованные группы захвата RE2. Именованные группы захвата можно использовать в поле destination с префиксом : , а на неименованные группы захвата можно ссылаться по их числовому индексу в значении regex , начиная с 1. Например:
"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 } ] }
Настроить переписывание
Необязательный
Используйте перезапись, чтобы отображать один и тот же контент для нескольких URL-адресов. Перезапись особенно полезна при сопоставлении с шаблоном, поскольку позволяет принять любой URL-адрес, соответствующий шаблону, и позволить клиентскому коду решать, что отображать.
Вы также можете использовать перезаписи для поддержки приложений, использующих pushState HTML5 для навигации. Когда браузер пытается открыть URL-путь, соответствующий указанному source или шаблону regex , браузеру будет предоставлено содержимое файла по destination URL-адресу.
Укажите перезаписи URL, создав атрибут rewrites , содержащий массив объектов (называемый «правилами перезаписи»). В каждом правиле укажите шаблон URL, который, при совпадении с путём URL запроса, инициирует ответ Hosting , как если бы сервису был предоставлен указанный целевой URL.
Вот базовая структура атрибута rewrites . Этот пример служит для index.html для запросов к несуществующим файлам или каталогам.
"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" } ] }
Атрибут rewrites содержит массив правил перезаписи, где каждое правило должно включать поля из таблицы ниже.
Firebase Hosting применяет правило перезаписи только в том случае, если файл или каталог не существует по URL-пути, соответствующему указанному source -адресу или шаблону regex . Когда запрос активирует правило перезаписи, браузер возвращает фактическое содержимое указанного destination файла вместо HTTP-перенаправления.
| Поле | Описание | |
|---|---|---|
rewrites | ||
source (рекомендуется)или regex | Шаблон URL, который, если совпадает с URL-адресом исходного запроса, заставляет Hosting применять переписывание
| |
destination | Локальный файл, который должен существовать Этот URL может быть относительным или абсолютным путем. | |
Прямые запросы к функции
Вы можете использовать rewrites для обслуживания функции с URL-адреса Firebase Hosting . Следующий пример — фрагмент обслуживания динамического контента с помощью Cloud Functions .
Например, чтобы направить все запросы со страницы /bigben на вашем Hosting сайте на выполнение функции 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)
}
} ]
}
Если
regionне указан вfunctionблоке конфигурацииhosting.rewrites, Firebase CLI попытается автоматически определить регион из исходного кода функции, который, если он не указан, по умолчанию будетus-central1. Если исходный код функции недоступен, CLI попытается определить регион из развёрнутой функции. Если функция находится в нескольких регионах, CLI требует указатьregionв конфигурацииhosting.rewrites.
Функция
pinTagдоступна только в Cloud Functions for Firebase (2-го поколения). С её помощью вы можете гарантировать синхронизацию каждой функции генерации динамического контента вашего сайта со статическими Hosting и конфигурацией Hosting . Кроме того, эта функция позволяет просматривать переписанные функции на каналах предварительного просмотра Hosting .Если добавить
"pinTag": trueв блокfunctionконфигурацииhosting.rewrites, то функция "pinned" будет развернута вместе со статическими ресурсами и конфигурацией Hosting , даже при выполнении. При откате версии сайта функция "pinned" также будет откачена.firebase deploy --only hosting Эта функция использует теги Cloud Run , которые имеют ограничение в 1000 тегов на сервис и 2000 тегов на регион. Это означает, что после сотен развёртываний самые старые версии сайта могут перестать работать.
После добавления этого правила перезаписи и развертывания в Firebase (с помощью firebase deploy ) ваша функция станет доступна по следующим URL-адресам:
Ваши поддомены Firebase:
PROJECT_ID .web.app/bigbenиPROJECT_ID .firebaseapp.com/bigbenЛюбые подключенные пользовательские домены :
CUSTOM_DOMAIN /bigben
Когда Firebase Hosting перенаправляет трафик в функцию, функция получает полный исходный путь запроса и строку запроса. Например, запрос к /bigben/hello/world?foo=bar на сайте вашего Hosting передаётся в функцию с полным путём и запросом. Убедитесь, что обработчик функции написан для обработки всего абсолютного URL , а не только базового пути, определённого в перезаписи.
При перенаправлении запросов к функциям с помощью Hosting поддерживаются следующие методы HTTP-запросов: GET , POST , HEAD , PUT , DELETE , PATCH и OPTIONS . Другие методы, такие как REPORT или PROFIND , не поддерживаются.
Прямые запросы к контейнеру Cloud Run
Вы можете использовать rewrites для доступа к контейнеру Cloud Run из URL-адреса Firebase Hosting . Следующий пример — фрагмент из процесса предоставления динамического контента с помощью Cloud Run .
Например, чтобы направить все запросы со страницы /helloworld на вашем Hosting сайте для запуска и работы экземпляра контейнера 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)
}
} ]
}
С помощью этой функции вы можете гарантировать Hosting что изменения в сервисе Cloud Run для генерации динамического контента вашего сайта будут синхронизированы с ресурсами и конфигурацией вашего статического Hosting . Кроме того, эта функция позволяет просматривать ваши переписанные тексты в каналах предварительного просмотра Cloud Run on Hosting .
Если вы добавите
"pinTag": trueв блокrunконфигурацииhosting.rewrites, ваши статические ресурсы и конфигурация Hosting будут закреплены в последней версии сервиса Cloud Run на момент развертывания. При откате версии сайта откатывается и версия закрепленного сервиса Cloud Run .Эта функция использует теги Cloud Run , которые имеют ограничение в 1000 тегов на сервис и 2000 тегов на регион. Это означает, что после сотен развёртываний самые старые версии сайта могут перестать работать.
После добавления этого правила перезаписи и развертывания в Firebase (с помощью firebase deploy ) ваш образ контейнера станет доступен по следующим URL-адресам:
Ваши поддомены Firebase:
PROJECT_ID .web.app/helloworldиPROJECT_ID .firebaseapp.com/helloworldЛюбые подключенные пользовательские домены :
CUSTOM_DOMAIN /helloworld
При перенаправлении запросов в контейнеры Cloud Run с Hosting поддерживаются следующие методы HTTP-запросов: GET , POST , HEAD , PUT , DELETE , PATCH и OPTIONS . Другие методы, такие как REPORT или PROFIND , не поддерживаются.
Для достижения наилучшей производительности разместите службу Cloud Run вместе с Hosting используя следующие регионы:
-
us-west1 -
us-central1 -
us-east1 -
europe-west1 -
asia-east1
Перезапись в Cloud Run с Hosting поддерживается в следующих регионах:
-
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
Создать собственный домен Dynamic Links
Вы можете использовать rewrites для создания Dynamic Links на основе собственных доменов. Подробную информацию о настройке собственного домена для Dynamic Links в документации Dynamic Links .
Используйте свой личный домен только для Dynamic Links
"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 } ] }Укажите пользовательские префиксы пути домена для использования в 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 } ] }
Для настройки Dynamic Links в файле firebase.json необходимо следующее:
| Поле | Описание | |
|---|---|---|
appAssociation | Необходимо установить
| |
rewrites | ||
source | Путь, который вы хотите использовать для Dynamic Links В отличие от правил, которые переписывают пути в URL-адреса, правила перезаписи для Dynamic Links не могут содержать регулярные выражения. | |
dynamicLinks | Должно быть установлено значение true | |
Настроить заголовки
Необязательный
Заголовки позволяют клиенту и серверу передавать дополнительную информацию вместе с запросом или ответом. Некоторые наборы заголовков могут влиять на обработку страницы и её содержимого браузером, включая контроль доступа, аутентификацию, кэширование и кодирование.
Укажите пользовательские заголовки ответа, специфичные для конкретного файла, создав атрибут headers , содержащий массив объектов заголовков. В каждом объекте укажите шаблон URL, который, если он совпадает с путём URL запроса, активирует Hosting для применения указанных пользовательских заголовков ответа.
Вот базовая структура атрибута headers . В этом примере заголовок CORS применяется ко всем файлам шрифтов.
"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" } ] } ] }
Атрибут headers содержит массив определений, где каждое определение должно включать поля из таблицы ниже.
| Поле | Описание | ||
|---|---|---|---|
headers | |||
source (рекомендуется)или regex | Шаблон URL, который, если совпадает с URL-адресом начального запроса, заставляет Hosting применять пользовательский заголовок.
Чтобы создать заголовок, соответствующий вашей странице 404 , используйте | ||
массив (под-) headers | Пользовательские заголовки, которые Hosting применяет к пути запроса Каждый подзаголовок должен включать пару | ||
key | Имя заголовка, например Cache-Control | ||
value | Значение заголовка, например max-age=7200 | ||
Подробнее о Cache-Control можно узнать в разделе Hosting , где описывается обслуживание динамического контента и размещение микросервисов. Вы также можете узнать больше о заголовках CORS .
Управление расширениями .html
Необязательный
Атрибут cleanUrls позволяет контролировать, должны ли URL-адреса включать расширение .html .
При true Hosting автоматически удаляет расширение .html из URL-адресов загружаемых файлов. Если в запросе добавлено расширение .html , Hosting выполняет перенаправление 301 на тот же путь, но удаляет расширение .html .
Вот как контролировать включение .html в URL-адреса с помощью атрибута cleanUrls :
"hosting": {
// ...
// Drops `.html` from uploaded URLs
"cleanUrls": true
}
Контроль завершающих косых черт
Необязательный
Атрибут trailingSlash позволяет контролировать, должны ли URL-адреса статического контента включать конечные слеши.
- Если
true, Hosting перенаправляет URL-адреса, добавляя в конце косую черту. - Если
false, Hosting перенаправляет URL-адреса, удаляя косую черту в конце. - Если не указано иное, Hosting использует только конечные слеши для файлов индекса каталога (например,
about/index.html).
Вот как контролировать завершающие слеши, добавив атрибут trailingSlash :
"hosting": {
// ...
// Removes trailing slashes from URLs
"trailingSlash": false
}
Атрибут trailingSlash не влияет на перезапись динамического содержимого, обслуживаемого Cloud Functions или Cloud Run .
Сопоставление шаблонов Glob
Параметры конфигурации Firebase Hosting широко используют нотацию сопоставления шаблонов с помощью extglob, аналогично тому, как Git обрабатывает правила gitignore , а Bower — правила ignore . Эта вики-страница содержит более подробную информацию, но ниже приведены пояснения к примерам, использованным на этой странице:
firebase.json— соответствует только файлуfirebase.jsonв корнеpublicкаталога.**— Соответствует любому файлу или папке в произвольном подкаталоге.*— Соответствует только файлам и папкам в корнеpublicкаталога.**/.*— Соответствует любому файлу, начинающемуся с.(обычно это скрытые файлы, например, в папке.git) в произвольном подкаталоге.**/node_modules/**— Соответствует любому файлу или папке в произвольном подкаталоге папкиnode_modules, которая сама может находиться в произвольном подкаталогеpublicкаталога.**/*.@(jpg|jpeg|gif|png)— Соответствует любому файлу в произвольном подкаталоге, который заканчивается ровно одним из следующих расширений:.jpg,.jpeg,.gifили.png
Пример полной конфигурации Hosting
Ниже представлен полный пример конфигурации firebase.json для Firebase Hosting . Обратите внимание, что файл firebase.json также может содержать конфигурации для других сервисов 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",
}
}