全部文章

3 分钟#cloudflare #tooling

把静态站丢上 Cloudflare

一个只有 assets、没有 main 的 Worker:没有请求计费,没有冷启动,没有运行时。顺便记几个每年都会忘的坑。

静态站部署这件事,我折腾过 Vercel、Netlify、GitHub Pages,最后落在 Cloudflare。

不是因为它最快——虽然它确实很快——而是因为它的部署模型足够无聊:一个只有 assets、没有 main 的 Worker。

没有脚本在跑,就没有冷启动,没有请求计费,没有"函数执行超时"。你的 dist/ 被推到边缘节点上,然后 CDN 直接吐文件。

配置短得离谱

{
  "name": "dream-blog",
  "compatibility_date": "2026-04-01",
  "assets": {
    "directory": "./dist",
    "html_handling": "auto-trailing-slash",
    "not_found_handling": "404-page"
  }
}

三个字段值得解释:

  • html_handling: auto-trailing-slash:让 /posts/hello-world 和 /posts/hello-world/ 指向同一个文件,不产生跳转链。
  • not_found_handling: 404-page:用你自己的 dist/404.html,而不是 Cloudflare 默认那页。
  • 没有 main 字段:这就是它"只是个静态站"的证据。

一键部署

npm run deploy

脚本做六件事:

1/6 环境检查   node 版本、wrangler 是否可用
2/6 构建       node build.mjs
3/6 产物校验   死链、h1、占位符、RSS、配置一致性
4/6 登录状态   wrangler whoami,没登录就停下
5/6 部署       dry-run 预检 -> wrangler deploy
6/6 线上自检   curl 五条关键路径

第 3 步是关键。永远不要部署没校验过的产物——线上排错的成本是本地的一百倍。

三个每年都会忘的坑

1. workers.dev 子域要先注册

第一次部署大概率会报:

You need to register a workers.dev subdomain before publishing

这不是权限问题,是账号还没在 Workers & Pages 里走完 onboarding。去控制台点一次就行,全局唯一、全账号共用。

2. _headers 不生效往往是因为缩进

Cloudflare 的 _headers 文件对格式很敏感——每条规则下面的响应头必须缩进两个空格,规则之间空一行:

/*
  X-Content-Type-Options: nosniff
  Referrer-Policy: strict-origin-when-cross-origin

/images/*
  Cache-Control: public, max-age=31536000, immutable

不缩进的话整段会被静默忽略,你会在三个月后才发现图片没有缓存。

3. 没有浏览器的机器用 Token

wrangler login 需要开浏览器。CI 里只能:

export CLOUDFLARE_API_TOKEN=你的token

Token 权限要包含 Workers Scripts:Edit、Account Settings:Read、User Details:Read、Zone:Read。少了哪一项,报错信息都不会直说是权限问题。

顺手加的几个头

X-Content-Type-Options: nosniff
Referrer-Policy: strict-origin-when-cross-origin
X-Frame-Options: SAMEORIGIN
Permissions-Policy: geolocation=(), microphone=(), camera=()

成本为零,但能挡掉一批低级的扫描告警。

为什么不直接 GitHub Pages

GitHub Pages 也很好,尤其是配合 Actions 的自动构建。区别在于:

  • Cloudflare 的免费额度对静态资源几乎无感,Pages 有 100GB/月的软限制
  • Cloudflare 的 _headers 能精细控制缓存与安全头,Pages 只能靠 _headers 支持的部分
  • 我的域名解析本来就在 Cloudflare

如果你的解析不在 Cloudflare,多出来的那一步 DNS 迁移可能就不值了。部署方案要跟着域名走,不是反过来。

回到顶部