Astro 部署到 Firebase Hosting(2026)

把静态 Astro 站点正确部署到 Firebase Hosting:firebase.json 配置、缓存头、干净 URL,以及那个会让你 404 失效的 SPA rewrite 陷阱。

对静态 Astro 站来说,Firebase Hosting 是个便宜又稳的归宿:免费 SSL、全球 CDN,免费额度还允许商用。部署本身就两条命令,真正要花心思的全在 firebase.json 里——rewrite 和缓存头配对一次,以后基本再也不用碰。

一句话总结

  • public 目录填 dist,“配置成单页应用(SPA)rewrite”那一项一定选 No。Astro 输出的是真实 HTML 路由,不是 SPA 外壳——接受 SPA rewrite 会让每个本该 404 的路径都返回 HTTP 200。
  • firebase.json 里加三条缓存规则:/_astro/** 哈希资源缓存一年且 immutable,图片和字体缓存 30 天,HTML 给短缓存。
  • astro.config.mjs 里的 site: 必须配,否则 sitemap 和 canonical 标签都会失效。
  • Spark(免费)档给你 10 GB 存储、每天 360 MB 流量、自定义域名,以及自动签发的 SSL,全部免费——而且允许商用。

什么时候该选 Firebase Hosting

满足下面任意一条,Firebase Hosting 就合适:

  • 想要可预测的账单,以及一个真能覆盖小站的免费额度。
  • 已经在用 Firestore、Auth 或 Cloud Storage,想统一到一个控制台、一个 CLI。
  • Astro 项目是静态输出(默认就是)——不需要服务端渲染。
  • 能接受跑一条 CLI 部署命令(或把它接进 GitHub Action)。

如果你重度依赖 SSR、边缘中间件,或者想要开箱即用、带预览链接的零配置 Git 部署,那就选 Vercel 或 Cloudflare Pages。完整取舍见 Firebase 和 Vercel 怎么选

计费档位与额度(截至 2026 年 6 月)

Spark(免费)Blaze(按量付费)
价格$0按用量、按月结算
Hosting 存储10 GB10 GB 免费,超出约 $0.026/GB
数据流量每天 360 MB每天 360 MB 免费,超出约 $0.15/GB
自定义域名包含包含
免费 SSL有(自动签发)有(自动签发)
商用允许允许

几百页的内容站基本能一直待在免费的 Spark 额度里。只有当你需要其他付费 Firebase 产品(比如用 Cloud Functions 做 SSR),或者每天流量超过 360 MB 时,才需要升 Blaze。下手前去 Firebase 定价页 核对当前数字——这些是用量配额,不是固定套餐。

实操步骤

1. 装 CLI 并登录

框架感知(framework-aware)的 hosting 需要 Firebase CLI 12.1.0 或更高版本。

npm install -g firebase-tools
firebase --version   # 应为 12.1.0 或更高
firebase login

2. 初始化 hosting——对 SPA rewrite 说 No

在 Astro 项目根目录跑。唯一关键的回答:问到是否配置成单页应用时,选 No。Astro 每个路由都出一个 HTML 文件,SPA rewrite 会把所有路径都指向 index.html——包括那些本该 404 的路径。

firebase init hosting
# ? What do you want to use as your public directory? dist
# ? Configure as a single-page app (rewrite all urls to /index.html)? No
# ? Set up automatic builds and deploys with GitHub? (自己选)

3. 写一份规避所有常见坑的 firebase.json

{
  "hosting": {
    "public": "dist",
    "ignore": ["firebase.json", "**/.*", "**/node_modules/**"],
    "cleanUrls": true,
    "trailingSlash": true,
    "headers": [
      {
        "source": "/_astro/**",
        "headers": [
          { "key": "Cache-Control", "value": "public, max-age=31536000, immutable" }
        ]
      },
      {
        "source": "**/*.@(jpg|jpeg|png|webp|avif|svg|woff2)",
        "headers": [
          { "key": "Cache-Control", "value": "public, max-age=2592000" }
        ]
      },
      {
        "source": "**/*.html",
        "headers": [
          { "key": "Cache-Control", "value": "public, max-age=300, s-maxage=3600" }
        ]
      }
    ]
  }
}

每一行为什么值得留着:

  • cleanUrls: true 去掉 .html 后缀,并把 /about.html 301 重定向到 /abouttrailingSlash: true 让 Firebase 补上结尾斜杠,这必须和 Astro 配置里的 trailingSlash: 'always' 一致,否则访问者会被卡进重定向循环。
  • /_astro/** 是 Astro 带内容哈希的 JS 和 CSS。文件名每次构建都变,所以一年的 immutable 缓存很安全,还能让回访者秒开。
  • 图片和字体给 30 天(max-age=2592000)。
  • HTML 给短浏览器缓存(5 分钟)外加更长的共享 CDN 缓存(s-maxage=3600),这样重新部署能很快被看到,同时 CDN 仍在分担流量。

4. 在 astro.config.mjs 里配 site:

sitemap 生成和 canonical URL 都读 site:。漏配的话,上线当天 sitemap 就是坏的。

import { defineConfig } from 'astro/config';
import sitemap from '@astrojs/sitemap';

export default defineConfig({
  site: 'https://yourdomain.com',
  trailingSlash: 'always',
  build: { format: 'directory' },
  integrations: [sitemap()],
});

5. 构建并部署

npm run build
firebase deploy --only hosting
# Hosting URL: https://your-project.web.app

6. 接上自定义域名

进 Firebase Console 的 Hosting,点 Add custom domain,按 DNS 提示配置——通常是两条指向 Firebase IP 的 A 记录。DNS 生效后 SSL 会自动签发,一般 1-24 小时。证书还没显示已签发就别把生产 DNS 切过去,否则这段空档里访问者会撞上证书警告。

7. 在生产环境核对缓存头

curl -sI https://yourdomain.com/ | grep -i cache-control
# cache-control: public, max-age=300, s-maxage=3600

curl -sI https://yourdomain.com/_astro/index.abc123.css | grep -i cache-control
# cache-control: public, max-age=31536000, immutable

8. 确认 404 真的返回 404

故意访问一个不存在的 URL,比如 /this-does-not-exist/,看状态码。如果返回 HTTP 200 还渲染了首页,说明 SPA rewrite 还在起作用——回去把它从 firebase.json 删掉。Google 会把软 404 当成薄内容,所以这一步每次部署都值得做。

curl -sI https://yourdomain.com/this-does-not-exist/ | head -1
# HTTP/2 404

Firebase 如何解析一个请求(rewrite 优先级)

当你想要的 rewrite 悄悄没生效时,几乎都是优先级顺序的问题。Firebase Hosting 按固定顺序应用规则,而且在 redirectsrewrites 内部,只有第一条匹配的规则会生效:

  1. 保留的 /__/* 命名空间(Firebase 内部)
  2. 配置的 redirects
  3. 精确匹配的静态内容(dist/ 里真实存在的文件)
  4. 配置的 rewrites
  5. 你的自定义 404.html
  6. 默认 404

实际要点:真实文件永远盖过 rewrite,每个块内部的规则顺序也很重要。如果一条 rewrite 被静态文件或更靠前的规则挡住了,参见 Firebase rewrite 没触发

容易踩的坑

  • 接受了默认的 SPA rewrite。 404 页面返回 200,Google 会把它们当薄页面收录。这是 Astro 部署到 Firebase 最常见的错误。
  • 忘了配缓存头。 Firebase 默认缓存保守,回访时会重新下载那些根本没变的资源。
  • DNS 切在 SSL 之前。 证书还没签发就把生产 DNS 指向 Firebase,访问者会一直看到安全警告,直到全网生效。
  • 指望纯 Hosting 跑 SSR。 静态 Hosting 只 serve 文件。SSR 需要 Astro 的 Node adapter 加上 Cloud Function 或 Cloud Run 后端,而这要 Blaze 计划。接好的函数若返回「function not found」,通常是区域或函数名对不上,不是部署失败(Firebase function not found)。
  • 漏配 astro.config.mjs 的 site: sitemap 和 canonical 标签都会失效。

常见问题

  • Firebase Hosting 真的免费吗: 小站是免费的。Spark 计划包含 10 GB 存储、每天 360 MB 流量、自定义域名和自动签发的 SSL,全部免费,而且允许商用。超出额度后转到 Blaze,按量付费,对静态内容来说非常便宜(截至 2026 年 6 月,超出流量约 $0.15/GB)。
  • 怎么在 Firebase 跑 Astro SSR: 加上 Astro 的 Node adapter,用 Cloud Function 或 Cloud Run 来 serve,这需要 Blaze 计划。大部分内容站和营销站用不上——静态输出更快也免费。
  • 能从 GitHub 自动部署吗: 可以。跑 firebase init hosting:github 生成一个 GitHub Action,推送时自动构建并部署,还能给 PR 创建预览频道。比手动部署更省心也更可靠。
  • 部署翻车怎么回滚: Firebase 保留发布历史。用 firebase hosting:versions:list 列出版本,用 firebase hosting:versions:clone 克隆好的那一版,再 firebase deploy --only hosting。或者在 Console 的 Hosting 里悬停到上一个发布、点 Roll back。两种都是几秒钟的事。
  • cleanUrls 和 trailingSlash 都要吗: trailingSlash: true 要和 Astro 里的 trailingSlash: 'always' 一起用,让两层保持一致。结尾斜杠设置不一致会导致重定向循环,或者产生重复 URL、分散你的 SEO 权重。

相关阅读

标签: #独立开发 #Astro #Firebase #部署 / 托管 #SSL #DNS