借助 Firebase 托管,您可以为对您网站的请求配置自定义托管行为。
您可以为托管配置什么?
指定要将本地项目目录中的哪些文件部署到 Firebase 托管。学习如何。
提供定制的 404/Not Found 页面。学习如何。
为您移动或删除的页面设置
redirects
。学习如何。为任何这些目的设置
rewrites
:添加
headers
以传递有关请求或响应的其他信息,例如浏览器应如何处理页面及其内容(身份验证、缓存、编码等)。学习如何。设置国际化 (i18n) 重写以根据用户的语言偏好和/或国家提供特定内容。学习如何(不同的页面)。
您在哪里定义托管配置?
您在firebase.json
文件中定义 Firebase 托管配置。当您运行firebase init
命令时,Firebase 会自动在项目目录的根目录下创建您的firebase.json
文件。
您可以在本页底部找到完整的firebase.json
配置示例(仅涵盖 Firebase 托管)。请注意, firebase.json
文件还可以包含其他 Firebase 服务的配置。
您可以使用Hosting REST API检查已部署的firebase.json
内容。
托管响应的优先顺序
本页描述的不同 Firebase 托管配置选项有时会重叠。如果存在冲突,Hosting 将使用以下优先顺序确定其响应:
如果您正在使用i18n rewrites ,则精确匹配和 404 处理优先顺序的范围会扩大以适应您的“i18n 内容”。
指定要部署的文件
默认的firebase.json
文件中包含的默认属性( public
和ignore
)定义了项目目录中的哪些文件应该部署到 Firebase 项目中。
firebase.json
文件中的默认hosting
配置如下所示:
"hosting": {
"public": "public", // the only required attribute for Hosting
"ignore": [
"firebase.json",
"**/.*",
"**/node_modules/**"
]
}
上市
必需的public
属性指定要部署到 Firebase 托管的目录。默认值为名为public
的目录,但您可以指定任何目录的路径,只要它存在于您的项目目录中即可。
以下是要部署的目录的默认指定名称:
"hosting": {
"public": "public"
// ...
}
您可以将默认值更改为要部署的目录:
"hosting": {
"public": "dist/app"
// ...
}
忽略
选修的ignore
属性指定在部署时要忽略的文件。它可以采用与Git处理.gitignore相同的方式处理.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/Not Found 页面
选修的
当用户尝试访问不存在的页面时,您可以提供自定义404 Not Found
错误。
在项目的public
目录中创建一个新文件,将其命名为404.html
,然后将自定义的404 Not Found
内容添加到文件中。
如果浏览器在您的域或子域上触发404 Not Found
错误,Firebase 托管将显示此自定义404.html
页面的内容。
配置重定向
选修的
如果您移动了页面或缩短 URL,请使用 URL 重定向来防止链接断开。例如,您可以将浏览器从example.com/team
重定向到example.com/about.html
。
通过创建包含对象数组(称为“重定向规则”)的redirects
属性来指定 URL 重定向。在每个规则中,指定一个 URL 模式,如果与请求 URL 路径匹配,则触发 Hosting 响应重定向到指定的目标 URL。
这是redirects
属性的基本结构。此示例通过向/bar
发出新请求将请求重定向到/foo
。
"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 托管在每个请求开始时将source
或regex
值与所有 URL 路径进行比较(在浏览器确定文件或文件夹是否存在于该路径之前)。如果找到匹配项,则 Firebase 托管源服务器会发送 HTTPS 重定向响应,告知浏览器在destination
URL 发出新请求。
场地 | 描述 | |
---|---|---|
redirects | ||
source (推荐)或 regex | 一个 URL 模式,如果与初始请求 URL 匹配,则触发 Hosting 应用重定向 | |
destination | 浏览器应在其中发出新请求的静态 URL 此 URL 可以是相对路径或绝对路径。 | |
type | HTTPS 响应代码
|
捕获用于重定向的 URL 段
选修的
有时,您可能需要捕获重定向规则的 URL 模式的特定部分( source
或regex
值),然后在规则的destination
路径中重新使用这些部分。
如果您正在使用source
字段(即,为您的 URL 模式指定一个 glob),您可以通过包含:
前缀来标识该段来捕获段。如果您还需要捕获该段之后的剩余 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
字段(即,为您的 URL 模式指定 RE2 正则表达式),则可以使用命名或未命名的 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,并让客户端代码决定显示什么。
您还可以使用重写来支持使用HTML5 pushState进行导航的应用程序。当浏览器尝试打开与指定source
或regex
URL 模式匹配的 URL 路径时,浏览器将在destination
URL 处获得文件的内容。
通过创建包含对象数组(称为“重写规则”)的rewrites
属性来指定 URL 重写。在每个规则中,指定一个 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
属性包含一组重写规则,其中每个规则必须包含下表中的字段。
如果 URL 路径中不存在与指定source
或regex
URL 模式匹配的文件或目录,则 Firebase 托管仅应用重写规则。当请求触发重写规则时,浏览器返回指定destination
文件的实际内容,而不是 HTTP 重定向。
场地 | 描述 | |
---|---|---|
rewrites | ||
source (推荐)或 regex | 一个 URL 模式,如果与初始请求 URL 匹配,则触发 Hosting 应用重写 | |
destination | 必须存在的本地文件 此 URL 可以是相对路径或绝对路径。 |
直接请求函数
您可以使用rewrites
来提供来自 Firebase 托管 URL 的功能。以下示例摘自使用 Cloud Functions 提供动态内容。
例如,要将来自您托管站点上/bigben
页面的所有请求定向到执行bigben
函数:
"hosting": {
// ...
// Directs all requests from the page `/bigben` to execute the `bigben` function
"rewrites": [ {
"source": "/bigben",
"function": "bigben",
"region": "us-central1" // optional (see note below)
} ]
}
添加此重写规则并部署到 Firebase 后(使用firebase deploy
),您的函数可通过以下 URL 访问:
您的 Firebase 子域:
PROJECT_ID .web.app/bigben
和PROJECT_ID .firebaseapp.com/bigben
任何连接的自定义域:
CUSTOM_DOMAIN /bigben
当使用 Hosting 将请求重定向到函数时,支持的 HTTP 请求方法是GET
、 POST
、 HEAD
、 PUT
、 DELETE
、 PATCH
和OPTIONS
。不支持REPORT
或PROFIND
等其他方法。
将请求直接发送到 Cloud Run 容器
您可以使用rewrites
从 Firebase 托管 URL 访问 Cloud Run 容器。以下示例摘自使用 Cloud Run 提供动态内容。
例如,要将来自您托管站点上/helloworld
页面的所有请求定向到触发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)
}
} ]
}
添加此重写规则并部署到 Firebase 后(使用firebase deploy
),您的容器映像可通过以下 URL 访问:
您的 Firebase 子域:
PROJECT_ID .web.app/helloworld
和PROJECT_ID .firebaseapp.com/helloworld
任何连接的自定义域:
CUSTOM_DOMAIN /helloworld
使用托管将请求重定向到 Cloud Run 容器时,支持的 HTTP 请求方法有GET
、 POST
、 HEAD
、 PUT
、 DELETE
、 PATCH
和OPTIONS
。不支持REPORT
或PROFIND
等其他方法。
目前,您可以在以下区域使用 Cloud Run 重写和托管:
-
asia-east1
-
asia-east2
-
asia-northeast1
-
asia-northeast2
-
asia-northeast3
-
asia-south1
-
asia-southeast1
-
asia-southeast2
-
australia-southeast1
-
europe-north1
-
europe-west1
-
europe-west2
-
europe-west3
-
europe-west4
-
europe-west6
-
northamerica-northeast1
-
southamerica-east1
-
us-central1
-
us-east1
-
us-east4
-
us-west1
创建自定义域动态链接
您可以使用rewrites
来创建自定义域动态链接。有关为动态链接设置自定义域的详细信息,请访问动态链接文档。
仅将您的自定义域用于动态链接
"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 } ] }
指定用于动态链接的自定义域路径前缀
"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 } ] }
在firebase.json
文件中配置动态链接需要以下内容:
场地 | 描述 | |
---|---|---|
appAssociation | 必须设置为
| |
rewrites | ||
source | 您要用于动态链接的路径 与重写 URL 路径的规则不同,动态链接的重写规则不能包含正则表达式。 | |
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
的更多信息。您还可以了解有关CORS标头的更多信息。
控制.html
扩展名
选修的cleanUrls
属性允许您控制 URL 是否应包含.html
扩展名。
当为true
时,Hosting 会自动从上传的文件 URL 中删除.html
扩展名。如果在请求中添加了.html
扩展名,Hosting 会执行301
重定向到同一路径,但会删除.html
扩展名。
以下是如何通过包含cleanUrls
属性来控制.html
在 URL 中的包含:
"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 提供的动态内容的重写。
全局模式匹配
Firebase 托管配置选项广泛使用 extglob 的glob 模式匹配符号,类似于 Git 处理gitignore
规则和Bower处理ignore
规则的方式。这个 wiki 页面是一个更详细的参考,但以下是对这个页面上使用的例子的解释:
firebase.json
— 仅匹配public
目录根目录中的firebase.json
文件**
— 匹配任意子目录中的任何文件或文件夹*
- 仅匹配public
目录根目录中的文件和文件夹**/.*
— 匹配任何以.
(通常是隐藏文件,比如在.git
文件夹中)在任意子目录中**/node_modules/**
— 匹配node_modules
文件夹的任意子目录中的任何文件或文件夹,该文件夹本身可以位于public
目录的任意子目录中**/*.@(jpg|jpeg|gif|png)
— 匹配任意子目录中恰好以下列之一结尾的任何文件:.jpg
、.jpeg
、.gif
或.png
完整托管配置示例
以下是 Firebase 托管的完整firebase.json
配置示例。请注意, 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",
}
}