使用 Cloud Functions 提供动态内容

使用 Firebase 托管时,您可以使用 Cloud Functions 来处理服务器端事务。这意味着您可以为 Firebase 托管网站动态生成内容。可以执行的操作如下所示:

  • 提供动态内容。 您可以通过函数执行服务器端逻辑以返回动态生成的响应,而不是仅提供静态内容。例如,您可以使用类似 /blog/<id-for-blog-post> 这样的网址。此网址格式可以指向一个函数,该函数以动态方式使用网址中的博文 ID 参数从您的 Firebase 实时数据库动态检索内容。
  • 预渲染单页应用以改进 SEO。这样您就可以创建动态 meta 标记,以便在不同社交网络上共享。
  • 使网页应用保持轻量级。 您可以通过 Cloud Functions 为 Firebase 托管网站创建 API,以异步检索内容。这样您可以通过使客户端代码保持轻量级,并通过函数异步加载内容,来减少网页应用的初始加载时间。

请注意,Firebase 托管受到 60 秒的请求超时时间的限制。对于生成时间可能超出 60 秒的动态内容,请考虑使用 App Engine 柔性环境

将 Cloud Functions 关联到 Firebase 托管

要将函数关联到 Firebase 托管,您需要设置 Cloud Functions、编写函数、创建重写规则并部署更改。要提升动态内容的性能,您可以选择调整缓存设置

为 Firebase 托管设置 Cloud Functions

如果您已经设置了 Cloud Functions for Firebase,可以跳过此步骤并开始创建 HTTP 函数

要为项目设置 Cloud Functions,您需安装最新版本的 Firebase CLI(需要 Node.js 6.3.1 或更高版本)。您可以按照 https://nodejs.org/ 上的说明安装 Node.js。安装 Node.js 会同时安装 npm

要查看您已安装的 Node.js 的版本,请在终端运行以下命令:

node --version

要安装最新版本的 Firebase CLI,请在终端运行以下命令:

npm install -g firebase-tools

要将您的本地计算机关联到 Firebase 帐号并获取对 Firebase 项目的访问权限,请运行以下命令:

$ firebase login

接着,您需要初始化 Cloud Functions。

如果您尚未使用托管功能初始化 Firebase 项目,请在项目目录中运行以下命令。出现提示时,选择初始化托管和 Cloud Functions。

firebase init

不过,如果您有一个现有的 Firebase 托管项目,请在您的项目目录中运行以下命令,以仅初始化 Cloud Functions。

firebase init functions

为您的托管网站创建 HTTP 函数

在您惯用的编辑器中打开 /functions/index.js,并将其内容替换为以下代码。这些代码可以创建一个名为 bigben 的 HTTP 函数。

const functions = require('firebase-functions');

exports.bigben = functions.https.onRequest((req, res) => {
  const hours = (new Date().getHours() % 12) + 1 // London is UTC + 1hr;
  res.status(200).send(`<!doctype html>
    <head>
      <title>Time</title>
    </head>
    <body>
      ${'BONG '.repeat(hours)}
    </body>
  </html>`);
});

将托管请求定向到您的函数

通过重写规则,您可以将匹配特定格式的请求定向到单个目标。例如,要定向您的托管网站上页面 /bigben 收到的所有请求以执行 bigben 函数,请打开 firebase.json,然后在 hosting 部分下添加以下 rewrite 配置。

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

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

请注意,Firebase 托管受到 60 秒的请求超时时间的限制。因此,即使您配置的 HTTP 函数的请求超时时间较长,如果您的函数需要的运行时间超出 60 秒,那么您仍会收到 HTTP 状态代码 504(请求超时)。为了支持这种动态内容,请考虑使用 App Engine 柔性环境

您可以在这里详细了解重写规则。

在本地运行动态内容

您可以使用 Firebase CLI 在本地部署和运行动态内容,这样就能在部署到生产环境之前对网站进行测试。

要使用此功能,firebase-tools 必须为 3.8.0 版或更高版本,firebase-functions SDK 必须为 0.5.7 版或更高版本。要更新二者,请在项目的 functions/ 目录中运行以下命令:

npm install --save firebase-functions@latest
npm install -g firebase-tools

要在本地运行动态内容,请使用 firebase serve

firebase serve --only hosting,functions # emulates local hosting code and local functions code
firebase serve --only hosting # emulates local hosting code, but uses production functions as proxies

此命令会输出一个网址,您可以访问该网址以查看或测试您的 Firebase 托管内容和 HTTP 函数。

部署

创建函数并设置重写规则后,请通过在终端运行以下命令来部署 Firebase 项目:

firebase deploy

部署后,您会注意到,通常情况下您可以通过以下网址访问您的函数:

https://us-central1-<your-project-id>.cloudfunctions.net/bigben

与重写规则中指定的路径匹配的 Firebase 托管网站上的所有流量将被代理到相应的函数。

体验示例函数

部署完成后,您可以在 Firebase 托管网站上转到 /bigben,以便查看其运行时的状态。

https://<your-project-id>.firebaseapp.com/bigben

使用 Cookie

将 Firebase 托管与 Cloud Functions 搭配使用时,Cookie 通常会从传入的请求中剥离出来。这是实现高效的 CDN 缓存行为所必需的。只有特别指定的 __session Cookie 可以传入到函数执行过程中。

__session Cookie(如果存在)会自动成为缓存键的一部分,也就是说,使用不同 Cookie 的两位用户绝不会收到彼此的已缓存响应。只有在您的函数根据用户授权提供不同的内容时,您才应当使用 __session Cookie。

管理缓存行为

Firebase 托管使用的是强大的全球 CDN,可使您的网站保持最快速度。Firebase 托管上的静态内容会被写入缓存,直到您部署新版本内容为止。由于函数会动态生成内容,因此函数处理的请求默认不会缓存在 CDN 中。您可以自行配置缓存行为,使应用速度加快并降低函数执行成本。

设置 Cache-Control

用于管理缓存的主要工具是 Cache-Control 标头。设置好后,您可以告知浏览器和 CDN 应将您的内容缓存多长时间。在函数中设置 Cache-Control 的方式如下所示:

res.set('Cache-Control', 'public, max-age=300, s-maxage=600');

上述标头执行以下三个操作:

  • 将缓存标记为公开。这意味着此内容可以被中间服务器缓存(在本例中为 CDN)。但在默认情况下,Cache-Control 设置为 private,这意味着只有用户的浏览器才能对其进行缓存。
  • 使用 max-age 告知浏览器可以缓存内容的秒数。在上例中,我们告知浏览器缓存五分钟。
  • 使用 s-maxage 告知 CDN 可以缓存内容的秒数。在上例中,我们告知 CDN 缓存十分钟。

对于 max-age,请将其值设为允许用户收到过时内容的最长时间。如果页面每几秒更改一次,应将 max-age 值设为一个较小的数字。但其他类型的内容可以安全地缓存数小时、数天甚至数月。

您可以在 Mozilla 开发者网络上了解有关 Cache-Control 标头的更多信息。

何时提供缓存的内容?

如果您设置了公共 Cache-Control 标头,则您的内容将基于以下元素在 CDN 中缓存:

  • 主机名
  • 路径
  • 查询字符串
  • Vary 中指定的标头的内容

Vary 标头决定着如何发送信号来说明请求的哪些部分对于确定响应至关重要。大多数时候,您无需担心此问题。Firebase 托管会自动确保针对常见情况为您的响应设置适当的 Vary 标头。这包括确保将您正在使用的任何会话 Cookie 或授权标头设为缓存键的一部分,以防意外泄露内容。

在某些高级使用场景中,您可能需要其他标头来影响缓存。在这种情况下,您可以只在响应中设置 Vary 标头:

res.set('Vary', 'Accept-Encoding, X-My-Custom-Header');

如果采用这些设置,两个具有不同 X-My-Custom-Header 标头的相同请求会分别被缓存。

发送以下问题的反馈:

此网页
需要帮助?请访问我们的支持页面