你已经有 build 好的静态站在 dist/ 里。你想 10 分钟之内把它挂到正式域名、带 HTTPS、能被 Google 抓到,但不想把 Firebase 文档读一遍。这篇按顺序给你跑下来,并告诉你哪些步骤可以跳。
问题背景
Firebase Hosting 是把静态站送到公网、配 SSL、走 CDN 的最快方式之一。官方 quickstart 能跑通,但少讲了几个东西——缓存头、trailing slash、preview channel——这些迟早会踩。本文把它们前置讲清楚,免得后面回头改。
开始前准备
- 一个 Google 账号,并且能打开 Firebase 控制台。
- 一个能本地 build 的静态站项目,比如 Astro / Vite / Hugo / 纯 HTML。
- 终端里已经有 Node.js 和 npm;
node -v、npm -v都能正常输出版本。 - 你知道自己的 build 命令和输出目录,通常是
npm run build和dist。 - 可选但推荐:已经买好的域名,并且你能修改 DNS 记录。
实操步骤
- 先创建 Firebase 项目:打开 Firebase 控制台,点 “Add project”,填写项目名,Google Analytics 按需开启或关闭,然后完成创建。
- 进入新项目,打开 Build > Hosting,点 “Get started”,这个浏览器标签先留着。你不一定要复制完整 quickstart,但这一步能确认 Hosting 已经启用。
- 回到本地项目,先 build 一次:
npm run build。确认输出目录存在,并且里面有 HTML 文件,比如 Astro / Vite 常见是dist/index.html。 - 安装并登录 Firebase CLI:
npm install -g firebase-tools,然后firebase login。如果你有多个 Google 账号,登录后跑firebase login:list确认当前账号没错。 - 把本地 repo 连接到 Firebase 项目:运行
firebase init hosting,选择 “Use an existing project”,选刚创建的项目,public directory 填 build 输出目录(dist/build/out),暂时不需要 CI 就对 GitHub deploy 选 “No”。 - 认真回答 SPA 问题:Astro / Hugo / 多页静态站选 “No”;只有那种所有路由都应该交给
/index.html的客户端路由应用才选 “Yes”。 - 检查生成文件。
.firebaserc里应该是你的 Firebase project ID,firebase.json里的hosting.public应该指向刚确认过的 build 目录。 - 给
firebase.json加上线配置:多页站通常用cleanUrls: true;HTML 用短缓存(no-cache或几分钟);带 hash 的静态资源用长缓存(Cache-Control: public,max-age=31536000,immutable)。 - 用 Firebase 本地预览,不只看框架 dev server:运行
firebase emulators:start --only hosting或firebase serve --only hosting,测试/、一篇文章页、/404、/sitemap.xml、/robots.txt。 - 正式部署:再跑一次
npm run build,然后firebase deploy --only hosting。打开命令输出里的https://<project-id>.web.app,按刚才同样路径点一遍。 *.web.app没问题后,到 Firebase 控制台 > Hosting > Add custom domain 绑定自定义域名。先加 TXT 验证记录,再按 Firebase 给的值添加 A 或 CNAME 记录。- 等待 DNS 和 SSL。多数域名几分钟能连上,但先给它几个小时,不要同时乱改其它配置。测试 apex、www,以及
http://到https://的跳转。 - 收尾上线:更新 canonical URL 和 sitemap base URL,到 Google Search Console 提交 sitemap,并记录 project ID、部署命令、public 目录和 DNS 记录。
参考 firebase.json
适合 Astro / Vite / Hugo 静态站的生产可用配置:
{
"hosting": {
"public": "dist",
"cleanUrls": true,
"trailingSlash": false,
"ignore": ["firebase.json", "**/.*", "**/node_modules/**"],
"headers": [
{
"source": "**/*.@(js|css|woff2|svg|webp|png|jpg)",
"headers": [{ "key": "Cache-Control", "value": "public,max-age=31536000,immutable" }]
},
{
"source": "**/*.html",
"headers": [{ "key": "Cache-Control", "value": "no-cache" }]
}
]
}
}
会反复用到的常用命令:
npm run build # 产出 dist/
firebase emulators:start --only hosting # 本地预览 :5000
firebase deploy --only hosting # 推到线上
firebase hosting:channel:deploy preview --expires 7d # 拉一个预览链接
firebase hosting:sites:list # 确认部署到了哪个 site
上线后验证
- 用无痕窗口打开
*.web.app和自定义域名,测试首页、深层文章 URL、404、sitemap、robots、移动端布局。 - 运行
firebase hosting:sites:list,确认部署到了目标项目;多个 Firebase 项目时这一步很关键。 - 在 Firebase 控制台 Hosting > Release history 里确认最新 release 时间和你刚才部署时间一致。
- DNS 稳定后,用 Search Console 的 URL Inspection 检查 Google 能抓取页面,并且 canonical 是你预期的域名。
容易踩的坑
- 还没创建 Firebase 项目就直接
firebase init,结果账号下没有可选项目。 - CLI 登录了错误的 Google 账号,把正式站部署到了个人测试项目。
- public 配成了源码目录而不是 build 产物——站能开但是空白页。
- 不小心勾了 “configure as a single-page app”,所有 URL rewrite 到
/index.html,多页站 SEO 直接废。 - HTML 没配
no-cache,部署后用户一直看到旧页。 - 跳过 DNS 验证那一步,结果卡在 “needs setup” 几个小时。
- 工作目录脏的时候直接 deploy,没看清传了什么上去。
这篇适合谁
所有想把静态站(Astro、Vite、Hugo、纯 HTML)配上 HTTPS、CDN、自定义域名,又想白嫖免费档的人。
这篇不适合谁
需要每次请求都 SSR、需要 websocket、需要按地域路由的应用——这些应该走框架原生平台。
FAQ
- 部署要花钱吗?: 不要。Spark 免费档覆盖部署、
*.web.app域名、自定义域名和 SSL。 - 自定义域名多久能用?: 设好 DNS 后一般 15 分钟到几小时,SSL 同步签发。
- 部署错了能回滚吗?: 能。Firebase 控制台 Hosting > Release history > 选历史版本 > Rollback,一键完成。
- 环境变量放哪?: 静态站的环境变量在 build 时打进去,放 CI 里,不是
firebase.json。 - preview 分支怎么搞?: 用
firebase hosting:channel:deploy <name>创建一个临时 preview URL,会自动过期。