使用 Firebase 托管实现本地化的 404 页面

Implementing localized 404 page with Firebase hosting

假设我的网络应用程序有两个语言环境:英语 (myapp.com/en/) 和法语 (myapp.com/fr/)。我想本地化我的 404 页面,因此 myapp.com/en/non-existentmyapp.com/non-existent 的请求将 return 404 页面的英文版本,而 myapp.comm/fr/non-existent 的请求将 return一个法国人。

但是,Firebase Hosting 似乎默认不提供此类功能,因为它只允许单个 404 页面(source)

那么,有没有一种方法可以使用 Firebase 托管实现本地化的 404 页面?

这个答案已经过时了。 Firebase 现在默认支持此功能。参见 the correct answer


实现此功能的一种方法是使用 rewrites:

{
  ...
  "hosting": {
    "rewrites": [
      {
        "source": "/fr/**",
        "destination": "/fr/404.html"
      },
      {
        "source": "**",
        "destination": "/en/404.html"
      }
    ]
  }

这将为 /fr/ 目录中不匹配的请求提供 /fr/404.html/ 页面,并为任何其他不匹配的请求提供 /en/404.html 页面。

这种方法的缺点是 returned 状态代码是 200 而不是 404。


更好的解决方案是重写不匹配的请求to Cloud Functions return 所需的 404 页面和 404 状态代码。请注意,404 页面必须位于 functions/lib 目录中,而不是 public.

此外,通过使用适当的 Cache-Control header,您可以允许 Firebase 托管缓存函数的输出,这样它们就不必 运行请求 404 页面的时间。

Firebase 配置:

{
  ...
  "hosting": {
    "rewrites": [
      {
        "source": "/fr/**",
        "function": "pageNotFoundFr"
      },
      {
        "source": "**",
        "function": "pageNotFound"
      }
    ]
  }

函数:

exports.pageNotFound = functions.https.onRequest((req, res) => {
    res.set("Cache-Control", "public, max-age=31536000")
    res.status(404).sendFile("en/404.html", {root: __dirname})
})

exports.pageNotFoundFr = functions.https.onRequest((req, res) => {
    res.set("Cache-Control", "public, max-age=31536000")
    res.status(404).sendFile("fr/404.html", {root: __dirname})
})

但是这种方法会重复代码,如果您有更多语言,可能会很混乱。


最好将请求处理程序提取到一个函数中:

exports.pageNotFound = functions.https.onRequest(notFoundHanler("en"))
exports.pageNotFoundFr = functions.https.onRequest(notFoundHanler("fr"))

function notFoundHandler(lang) {
    return function (req, res) {
        res.set("Cache-Control", "public, max-age=31536000")
        res.status(404).sendFile(`${lang}/404.html`, {root: __dirname})
    }
}

更新: 我向 Firebase 提交了多个 404 页面的功能请求,他们回复说会考虑。

自 2020 年 8 月 12 日起,Firebase 托管现在包括对 i18n internalization.

的支持

使用方法如下:

  1. 在您的 public 目录下创建一个新目录来存放这些本地化文件(例如 localized)。
  2. 更新您的 firebase.json 文件以包含对此新目录的引用:
// firebase.json

"hosting": {

  "public": "public",

  "ignore": [
     // ...
  ],

  "i18n": {
    "root": "/localized"  // directory that contains your "i18n content"
  }

  // ...
}
  1. localized 目录下,创建一个名为 fr 的新目录,您可以在其中添加法语 404.html 文件。
  2. 运行 firebase deploy 部署您的网站,现在您的法语用户应该被重定向到正确的页面:)

有关国家和语言代码的详细信息,请参阅 Firebase Docs