Firebase Hosting 部署失败

CLI 版本、配额、firebase.json 三件事最常见。

firebase deploy --only hosting 跑到一半抛 HTTP Error: 400Failed to make request to https://firebasehosting.googleapis.com/...Site quota exceeded 这类错误——Firebase Hosting 的部署链路相对短,失败原因 90% 集中在 CLI 版本、auth token、firebase.json 配置和日配额这四件事上。本文按命中率列出 5 类常见原因,并给一条从 --debug 看完整日志、到逐项排查的修复路径。

常见原因

按命中率从高到低。

1. CLI 版本过旧或与项目不匹配

Firebase CLI 每隔几个月就改 API 协议,老版本(特别是 v11 以下)经常抛 Unexpected error: ...Failed to parse host 之类含糊错误。

$ firebase --version
9.22.0   # 太老了,建议至少 13.x

如何判断:报错里出现 Cannot read property 'X' of undefinedUnexpected token in JSON、而你没改过任何配置——大概率 CLI 版本问题。

2. Auth token 过期或换了 Google 账号

CLI 在 ~/.config/configstore/firebase-tools.json 里存登录态,token 过期或你切到了别的 Google 账号时,会报 HTTP Error: 401, Request had invalid authentication credentialsFailed to authenticate, have you run firebase login?

如何判断firebase login:list 看当前登录的账号,是不是这个项目所属的那个。

3. firebase.json 的 public 路径和 build 产物对不上

public 字段指向被部署的目录。Astro 默认 build 到 dist/、Next.js 静态导出到 out/、Vite 到 dist/,但很多项目沿用了 firebase init 默认的 "public": "public",结果上传的是空目录。

// firebase.json — Astro 项目的典型配置
{
  "hosting": {
    "public": "dist",
    "ignore": ["firebase.json", "**/.*", "**/node_modules/**"],
    "rewrites": [{ "source": "**", "destination": "/index.html" }]
  }
}

如何判断firebase deploy 日志显示 i hosting[project]: found 0 files in public——上传了 0 个文件。

4. 项目超出免费配额(Spark 计划)

Spark 计划每天每个 site 限 10GB 出站流量、每月 360MB 存储,部署时如果新构建产物把存储推过 10GB 累计上限,会报 Site quota exceededHosting site is over its quota

如何判断:Firebase Console → Hosting → Usage 标签,看 “Storage” 和 “Data transfer” 两个数字是否接近上限。

5. firebase.json 里 rewrites / redirects 语法错误

常见手写错误:sourcedestination 反了、glob 模式 ** 写成 *、redirects 的 type 不是 301/302。CLI 在部署时才校验,所以本地看着没问题。

// 错误示例:缺少必需的 type
"redirects": [
  { "source": "/old", "destination": "/new" }
]
// 正确
"redirects": [
  { "source": "/old", "destination": "/new", "type": 301 }
]

如何判断:日志里出现 Invalid hosting configurationSpecified "redirects" config is not valid

最短修复路径

按”先拿完整日志、再排升级 / 重登 / 配置 / 配额”的顺序。

Step 1:用 --debug 重跑拿到完整堆栈

默认输出会折叠真正的报错。加上 --debug

firebase deploy --only hosting --debug 2>&1 | tee firebase-deploy.log

日志里搜 [ERROR]HTTP Error:,附近通常有真正的根因(PERMISSION_DENIED / INVALID_ARGUMENT / QUOTA_EXCEEDED 等)。

Step 2:升级 CLI 并重新登录

# 全局升级
npm install -g firebase-tools@latest
firebase --version   # 期望 13.x 或更新

# 重新登录刷新 token
firebase logout
firebase login

# 确认当前登录账号
firebase login:list
firebase projects:list   # 看是不是有这个 project_id

如果你在 CI 里部署,应该用 firebase login:ci 拿一个 token 存到环境变量 FIREBASE_TOKEN,而不是依赖交互式登录。

Step 3:校验 firebase.json 的 public 指向正确

# 看本地 build 产物
ls -la dist/   # 或 out/、build/、public/,看你的框架

# 看 firebase.json 里写的是什么
cat firebase.json | grep public

两者必须一致。常见框架对照:

框架build 输出目录
Astro (static)dist
Next.js (static export)out
Vitedist
Create React Appbuild
Vue CLIdist

也可以用 firebase deploy --only hosting --dry-run(如果 CLI 版本支持)只校验配置不真正上传。

Step 4:本地起 emulator 提前发现问题

firebase emulators:start --only hosting
# 在 http://localhost:5000 打开,跟生产行为一致
# rewrites / redirects 配置有问题 emulator 也会抛同样错误

修完配置在 emulator 验证通过,再 deploy。

Step 5:配额超限的应对

如果 Step 1 日志显示 QUOTA_EXCEEDED

  1. Firebase Console → Hosting → Usage → 看当前数字。
  2. 临时方案:删除一些历史版本(Hosting → Release history → 点旧的 release → Delete)以释放存储。
  3. 长期方案:升级到 Blaze 按量付费计划(10GB 之后每 GB 约 $0.026 流量、$0.026 存储/月),不是真的”按月固定收费”,小站点几乎免费。

Step 6:rewrites / redirects 语法校验

把 firebase.json 贴进 hosting 配置 schema 比对字段名。或者本地用 npx ajv-cli 跑 JSON schema 校验:

npx ajv-cli validate \
  -s https://raw.githubusercontent.com/firebase/firebase-tools/master/schema/firebase-config.json \
  -d firebase.json

预防建议

  • package.json 里 pin firebase-tools 版本("firebase-tools": "13.15.4")并加进 devDependencies,团队 / CI 永远用同一版。
  • CI 用 firebase login:ci 生成的 token 部署,避免 token 过期影响发版。
  • 配置 GitHub Actions 在 PR 上跑 firebase hosting:channel:deploy preview 预览部署,主分支合并前就能发现 firebase.json 问题。
  • 部署前一步先跑 firebase emulators:exec "echo ok" --only hosting,配置错的话本地就 fail。
  • Spark 配额监控:在 Firebase Console 里设置 Budget alert(哪怕没开 Blaze,也能在 80% 流量时邮件提醒)。

相关阅读

标签: #部署 / 托管 #排查 #排查 #Firebase