Firebase Hosting rewrite 不生效

2026 最新:SPA / 函数的 rewrite 没触发——顺序 / 同名静态文件 / 函数区域。

你在 firebase.json 里配了 rewrites,比如 /api/** 转到 Cloud Function、** 转到 SPA 的 index.html,部署后访问 /api/xxx 应该走函数但直接 404;或者 SPA 的深层链接 /dashboard/123 返回 404 而不是 index.html——配置看起来对,结果就是不生效。

Firebase Hosting 的 rewrite 规则有几条”看不见”的优先级:静态文件 > rewrites 第一条匹配 > 404.html。理解这套优先级,才能修对地方。

常见原因

按命中率从高到低:

1. rewrites 顺序错(先匹配先生效)

{
  "rewrites": [
    { "source": "**", "destination": "/index.html" },  // ❌ 这条吃掉所有路径
    { "source": "/api/**", "function": "api" }         // 永远到不了
  ]
}

把更具体的放前面。

如何判断:rewrite 配置里 ** 通配在 /api/** 前面?

2. 同路径有静态文件,被静态优先

如果 public/api.html 存在,访问 /api 会拿静态文件而不是 rewrite 到 function。

如何判断ls public/ 看是否有跟 rewrite source 冲突的文件。

3. 函数 region 跟 rewrite region 不一致

{
  "rewrites": [
    { "source": "/api/**", "function": { "functionId": "api", "region": "us-east1" } }
  ]
}

函数实际部署在 us-central1,rewrite 找 us-east1——404。

如何判断firebase functions:list 看函数 region,跟 rewrite 里写的对。

4. 函数没真的部署成功

deploy 命令成功,但函数 build 失败被跳过(看 firebase-deploy-permission-denied 类似的 silent fail)。rewrite 指向一个不存在的函数。

如何判断firebase functions:list 看函数名是否在列表里。

5. 用了 cleanUrls / trailingSlash 改变路径

{
  "cleanUrls": true,      // /about.html → /about
  "trailingSlash": false  // /about/ → /about
}

启用这些后,你的 source pattern 也要相应调整,否则匹配不上。

如何判断:config 里有 cleanUrls / trailingSlash,rewrite source 还在用旧路径。

6. firebase.json 改了但没 deploy hosting

firebase deploy --only functions 不会更新 rewrite,必须 --only hosting 或全量 deploy。

如何判断:最近一次 firebase deploy 命令带了什么 flag?

最短修复路径

Step 1:rewrites 重排序——具体的放前面

{
  "hosting": {
    "public": "dist",
    "rewrites": [
      { "source": "/api/**", "function": { "functionId": "api", "region": "us-east1" } },
      { "source": "/webhooks/**", "function": "webhookHandler" },
      { "source": "**", "destination": "/index.html" }
    ]
  }
}

规则:从最具体到最通用排序,最后一条才是 SPA fallback。

Step 2:删掉冲突的静态文件

ls public/
# 如果有 api.html、api/index.html 等,移走
mv public/api.html /tmp/
firebase deploy --only hosting

Step 3:对齐函数 region

# 1. 看函数实际 region
firebase functions:list

# 2. firebase.json 里 rewrite region 匹配
{
  "source": "/api/**",
  "function": {
    "functionId": "api",
    "region": "asia-east1"
  }
}

或者函数代码里改 region 重新部署。

Step 4:确认部署 hosting 配置

firebase deploy --only hosting

# 如果改了 firebase.json 又改了函数:
firebase deploy --only hosting,functions

# 看本次部署的实际 rewrites
firebase hosting:channel:list  # 看部署版本

Step 5:用 emulator 本地验证

firebase emulators:start --only hosting,functions

# 访问 http://localhost:5000/api/test
# 看是否走 function

local 正常 = 生产配置 / 部署问题;local 也错 = 配置本身错。

Step 6:用 curl 看实际响应

curl -v https://your-app.web.app/api/test

# 200 + 函数响应 = rewrite 工作了
# 404 + HTML 内容 = 没 rewrite,被静态/SPA fallback 接走
# 404 + 空 = 路径不存在,rewrite 也没匹配

Step 7:复杂规则用 redirects + rewrites 组合

{
  "redirects": [
    { "source": "/old-api/**", "destination": "/api/:1", "type": 301 }
  ],
  "rewrites": [
    { "source": "/api/**", "function": "api" },
    { "source": "**", "destination": "/index.html" }
  ]
}

redirects 优先级最高,会先走。

预防建议

  • firebase.json 加注释(用 jsonc 或外部 doc),rewrite 顺序要写清楚为什么
  • CI 里加一步:deploy 后跑 curl 测试每个关键 rewrite path
  • public/ 目录里别放 api.htmlwebhooks.html 这类容易冲突的名字
  • 项目用一个固定 region,函数全部部署到同一个,rewrite 不再手写 region
  • firebase.json 改动走 PR review,避免不小心改坏顺序
  • firebase deploy 默认全量,明确知道改了什么时才用 --only
  • 本地用 emulator 跑一遍完整 routing 再 deploy
  • 部署后用 production URL 测,不要只信 emulator

相关阅读

标签: #后端 #排查 #排查 #Firebase