跳到正文
跟我做
开发者 AI 实战12 分钟Cloudflare

从 GitHub 到 Cloudflare:把静态站真正上线

按我们实际踩坑的顺序,从域名 NS、GitHub 托管、本地构建到 Workers 部署和线上确认。重点不是命令,是哪一步会白等一晚上。

约 12 分钟
本页目录
  1. 这篇解决什么问题
  2. 0. 我们实际走的链路
  3. 1. 域名:买在哪、为什么要改 NS、改之前关什么
  4. 1.1 买域名
  5. 1.2 为什么要改 DNS 服务器
  6. 1.3 改 NS 之前,先关掉域名展示页
  7. 1.4 绑定 apex 和 www
  8. 2. 代码托管:GitHub 推上去之后 CI 看什么
  9. 3. 构建:静态站怎么编译、产物在哪、本地怎么验证
  10. 3.1 本地构建
  11. 3.2 构建前跑什么
  12. 3.3 Cloudflare 的 Build command 怎么填
  13. 4. 部署:Git 推送自动构建 vs 命令行直传
  14. 4.1 自动:push master
  15. 4.2 手动:本机 wrangler deploy
  16. 5. Deployments 显示成功,为什么线上还是旧的
  17. 5.1 我们遇到的现象
  18. 5.2 先按这个顺序查
  19. 5.3 这次怎么解决的
  20. 5.4 验证时别被代理骗了
  21. 6. 出问题时:构建卡住、代理、令牌
  22. 6.1 构建卡住或失败
  23. 6.2 代理
  24. 6.3 令牌和权限
  25. 6.4 回滚
  26. 7. 上线检查清单
  27. 8. 哪些是实测,哪些是未实测
  28. 下一步读什么

30 秒速查

  • 先买域名、接 Cloudflare,等 zone Active 再绑域名
  • GitHub push 只是早期信号,不等于部署
  • Cloudflare Build command 用 npm run verify,构建藏在它最后一步
  • Deployments Ready 不等于线上更新,必须 curl
  • 所有线上 curl 加 --noproxy '*'

这篇解决什么问题

网上讲上线的文章,大多是把官方文档换个说法:点这里、填那里、等一会儿。真到自己做,卡住的地方往往不是“不会点”,而是:

  • 域名注册商把 DNS 锁住了,改不了 NS;
  • GitHub 绿了,Cloudflare 却没部署;
  • Deployments 显示 Ready,线上还是旧页面;
  • 本机代理让 curl 超时,误判成站点挂了。

这篇按我们实际走的顺序写。每一步都回答三件事:做什么、为什么、怎么确认成了。没实测过的地方会标出来。

0. 我们实际走的链路

ename 买域名
→ Cloudflare Add a site
→ 关掉域名展示页,改 NS
→ 等 zone Active
→ Worker 绑 apex / www
→ GitHub 推 master
→ Cloudflare Workers Builds:npm run build → npx wrangler deploy
→ curl --noproxy '*' 验证线上

这不是官方分类,是实际顺序。域名和 DNS 在前,是因为后面 Worker 绑自定义域名依赖 zone;代码和构建在后,是因为本地能跑通再谈上线。

1. 域名:买在哪、为什么要改 NS、改之前关什么

1.1 买域名

我们买在 ename。选它没有神秘理由,就是当时能买、能改 NS。价格和续费我没记录,未实测,别把本文当购买建议。

买完先别急着写代码。先确认两件事:注册商后台能不能改 NS,域名有没有被“展示页”之类的功能占用。后面会卡在这。

1.2 为什么要改 DNS 服务器

Cloudflare 要接管 DNS,才有 zone 这个概念。Worker 绑定自定义域名、apex 跳转、缓存和证书,都建立在这个 zone 上。

apex 域名(genwozuo.com)本来就不适合直接 CNAME 到别处;改 NS 让 Cloudflare 成为权威 DNS,是最干净的路。

怎么确认成了:Cloudflare Overview 显示 Active;命令行查 NS:

dig +short NS genwozuo.com @1.1.1.1

我们实测返回:

frida.ns.cloudflare.com.
sri.ns.cloudflare.com.

两条都在,才算 NS 生效。

1.3 改 NS 之前,先关掉域名展示页

这一步最容易白忙。ename 后台如果开着「域名展示页」,点修改 DNS 会直接报:

域名已设置展示页,不能修改DNS

处理顺序是:管理中心 → 我的域名 → 域名 → 更多功能 → 域名展示页 → 关闭。关掉之后,再去 DNS 那一行点「修改DNS」,填 Cloudflare 给的两个 NS。

注意:解析列表里的 NS 行是锁死的,不能直接删改;入口在 DNS 行的「修改DNS」,不是在记录列表里编辑。

怎么确认成了:回到域名管理页,NS 已经变成 Cloudflare 的两个地址;Cloudflare 侧从 Pending 变成 Active。NS 生效不是秒级,别在 Pending 时反复绑域名。

1.4 绑定 apex 和 www

apex 用 Worker 的自定义域名:

Workers & Pages → genwozuo → Domains → Add custom domain → genwozuo.com

Cloudflare 会自动生成一条 Worker 类型的记录,不用手动建。

www 有两条路:

  • 首选(我们现在线上):Domains → Add custom domain,填 www.genwozuo.com。
  • 如果界面报 No zones match:退回 DNS 记录 + Worker Route。我们早先实测过这条:DNS 加一条 A / www / 192.0.2.1(RFC 5737 占位地址)/ Proxy 开启;Worker → Domains → Add Route,填 www.genwozuo.com/*,Failure mode 保持 Fail closed。

第一条是当前线上在用的;第二条是备选,不是首选。两条都能成,区别是入口和后续维护方式。

apex 到 www 的 301 用 Redirect Rule:

Hostname equals genwozuo.com
→ https://www.genwozuo.com + 原路径
→ 301,保留 query string

怎么确认成了:

curl -sSI --noproxy '*' https://www.genwozuo.com/ | head -1
curl -sI  --noproxy '*' https://genwozuo.com/ | grep -i location

第一条应为 HTTP/2 200;第二条应看到 301 到 https://www.genwozuo.com/...。少一个,域名就没完全通。

2. 代码托管:GitHub 推上去之后 CI 看什么

仓库在 GitHub 私有组织 genwozuo 下,Cloudflare 的 Git 连接同一个组织。日常在 dev 上改,发布时快进到 master。

GitHub Actions 的 verify job 跑的是 verify 那几项(verify:fast / verify:tutorials / verify:media / verify:site / verify:ui),这是早期信号,不是部署闸门。GitHub Free 私有仓库不强制要求检查通过才能合并,所以“Actions 绿了”不等于“Cloudflare 会部署”。

CI 红怎么看:先点进 job 日志。Annotations 只写 exit code 1,不是日志;真正的报错在 job 输出里。已知坑是 Node 版本:Astro 7 要求 Node >= 22.23.4,我们 CI 固定用 24。

怎么确认成了:Actions 里最新一次 verify 是绿的,job 日志里能看到类型检查、教程测试、媒体测试、站点检查依次通过。绿了只代表代码过了本地这层,不代表已上线。

3. 构建:静态站怎么编译、产物在哪、本地怎么验证

3.1 本地构建

npm run build

产物在 dist/。我们的站构建后是 70 个页面(这个数字会随文章增加,别把它当固定值)。

构建完别只看退出码。至少确认:

test -f dist/index.html
find dist -name '*.html' | wc -l

第一条通过、第二条数量和预期差不多,才算产物真的在。再本地起一个静态服务看页面:

npm run serve:dist

页面能打开、样式在、关键路由不 404,才算本地构建可用。

3.2 构建前跑什么

本地发布前跑:

npm run verify

它会跑类型检查、教程测试、媒体测试和站点检查。你要的是 exit 0,不是“看起来没报错”。

3.3 Cloudflare 的 Build command 怎么填

我们线上配置:

Build command:  npm run verify
Deploy command: npx wrangler deploy

注意构建是藏在 verify 里面的:本项目的 verify 最后一步是 verify:site,它会先跑 npm run build 生成 dist/,再校验站点。所以 Build command 只填 npm run verify,不要再拼一次 npm run build。

换项目时先确认你的 verify 里有没有构建这一步:有,就填 npm run verify;没有,才填 npm run verify && npm run build。以你项目的 package.json 为准,别照抄。

怎么确认成了:本地 dist/index.html 存在、页面数对、npm run verify exit 0;Cloudflare 构建日志里能看到 verify 跑完,以及它内部触发的 build 成功,并生成了 dist。

4. 部署:Git 推送自动构建 vs 命令行直传

4.1 自动:push master

日常发布走这条:

git checkout master
git merge --ff-only dev
git push origin master

Cloudflare 只监听 master。push 到 dev 不会触发部署,这是最容易误会的一点。

Workers Builds 的配置:

  • Build command:npm run verify(构建在 verify:site 里)
  • Deploy command:npx wrangler deploy
  • Preview builds:关闭
  • 分支:master

适合谁:日常发布、希望保留构建记录、希望平台帮你跑构建的人。

4.2 手动:本机 wrangler deploy

npm run build
npx wrangler deploy

适合谁:急修、调试、Cloudflare 构建队列卡住、需要立刻把本地验证过的产物传上去的人。

这条路的代价:你绕过了 Cloudflare 的构建闸门,所以本地必须先 npm run verify + npm run build。本地没验证就直传,等于把线上当测试环境。

怎么确认成了:Deployments 里出现最新记录,commit/时间对得上。但先别急着说“上线了”,看第 5 节。

5. Deployments 显示成功,为什么线上还是旧的

这是本文最重要的一节。

5.1 我们遇到的现象

今晚实际发生:

  • Cloudflare Deployments 里有两条提交,一条 Queued 卡了 5 分钟,一条 Skipped;
  • 点 Retry 也没救回来;
  • 本地 npm run build 成功,70 页;
  • 线上打开还是旧版:抓 HTML 能看到旧 class 名,新路由 404。

“构建成功”“部署记录存在”“线上已更新”是三件事,不是一件。

5.2 先按这个顺序查

  1. 看 commit,不看 badge:Deployments 里最新记录的 commit 是不是你刚推的那条?时间对不对?
  2. 看分支:是不是 push 到了 master?dev 不触发部署。
  3. 看状态:Queued 是还在排队,Skipped 是这次没构建;两个都不是“成功”。
  4. 绕过代理再抓页面:curl --noproxy '*',抓 HTML 看新 class 名,访问新路由看是不是 404。
  5. 看部署列表:npx wrangler deployments list,确认最新一次部署的时间和 commit。

如果前三步就发现是 Queued/Skipped,别等。等下去大概率还是白等。

5.3 这次怎么解决的

不是等,是本地 build 完直接传:

npm run verify
npm run build
npx wrangler deploy

实测 13 秒完成。传完再抓页面,新 class 名出现、新路由 200,才算真的更新。

为什么这条能成:它绕过了 Cloudflare 的构建队列,直接把本地 dist 上传。代价是本地必须自己承担验证责任。

5.4 验证时别被代理骗了

本机代理 127.0.0.1:7862 不稳定时,线上探测会返回 000 或 30 秒超时。站点其实是 200,代理把它伪装成挂了。

所有线上验证都加:

curl --noproxy '*' -sSI https://www.genwozuo.com/ | head -1

不加这个参数,你可能会把“代理坏了”误判成“Cloudflare 挂了”,然后白折腾一晚上。

怎么确认真的更新了:同时满足三条——最新 Deployments 的 commit 对、curl --noproxy '*' 返回 200、抓到的 HTML 里有这次的新 class 或新路由。少一条都不算。

6. 出问题时:构建卡住、代理、令牌

6.1 构建卡住或失败

先看 Cloudflare 构建日志,不是只看 Deployments 的颜色。常见原因:

  • Node 版本不对:本地 24,平台也要 24;
  • 依赖装不上:看是不是走了 npm ci、lockfile 有没有提交;
  • Build command 写错:npm run build 和 npm run verify 别混;
  • 超时或内存:构建时间突然变长,先看是不是多了大文件。

如果 Queued 卡很久、Retry 无效,直接用本地 wrangler deploy 救急;不要整晚等队列。

6.2 代理

  • curl 一律加 --noproxy '*';
  • Node 脚本如果必须走代理,用 NODE_USE_ENV_PROXY=1 显式开;
  • 不要把代理的 000/超时当成站点故障,先换无代理再测。

6.3 令牌和权限

  • wrangler login 只在本机做,不要把登录态提交到仓库;
  • CI/Cloudflare 用平台自己的凭据,不要往代码里塞 token;
  • GitHub App 要能读对应仓库;Cloudflare token 按最小权限给;
  • 永远不提交 .env、CLOUDFLARE_API_TOKEN、私钥。

具体 token 需要哪些 scope,我没逐项记录,未实测;按最小权限原则给,报 403 时先查账号、zone 和仓库权限。

6.4 回滚

线上坏了,先回滚,再查原因:

Cloudflare → Deployments → 选上一个 Ready → Rollback

界面没有入口时:

npx wrangler rollback

回滚后仍要跑第 5 节的线上验证,别假设回滚一定生效。

7. 上线检查清单

改 DNS 前

  • 域名注册商能登录,知道 NS 在哪改
  • 域名展示页已关闭
  • 记下原 NS,万一要退回
  • Cloudflare zone 已添加

push 前

  • npm run verify exit 0
  • npm run build 成功,dist/index.html 存在
  • 本地页面打开正常
  • 分支是 master,不是 dev

部署后

  • Deployments 最新 commit 是这次提交
  • 状态是 Ready,不是 Queued/Skipped
  • curl --noproxy '*' 返回 200
  • HTML 里有新 class/新内容
  • 新路由不是 404
  • apex 301 到 www
  • 记下上一个 Ready,出事能回滚

8. 哪些是实测,哪些是未实测

部分 状态
ename 买域名、关展示页、改 NS 实测
Cloudflare zone Active、apex/www 绑定、301 实测
GitHub Actions、Cloudflare Workers Builds 实测
本地 70 页构建、wrangler deploy 13 秒 实测
Queued/Skipped、Retry 无效、线上旧版 实测
代理导致 000/30s 实测
域名价格/续费 未实测
token 具体 scope 未实测
522/526 等 SSL 报错 未实测

下一步读什么

站点上线后,内容怎么从 0 开始,看从 0 开始:第一台自动化工作台;构建和命令基础,先看Node.js 安装。

如果遇到 ffmpeg 或 npm 的环境问题,分别看ffmpeg PATH 排错和npm install 报错。

常见问题

一定要用 Cloudflare 吗?

不一定。Vercel、Netlify 也能托管静态站。本文写的是我们实际走的 Cloudflare Workers 这条线,换平台时域名和构建部分可以借鉴,部署和验证要按平台改。

域名一定要改 NS 吗?

用 Cloudflare 的 Worker 自定义域名,域名要先接入 Cloudflare 成为一个 zone,改 NS 是最干净的方式。apex 域名做 CNAME 本来就受限,别在这上面绕。

Deployments 显示 Ready 就是更新了吗?

不是。Ready 只说明那一次构建部署完成,不保证它是最新提交,也不保证你访问到的是新版本。必须用无代理 curl 查页面内容和新路由。

可以直接 wrangler deploy 吗?

可以,适合急修和调试,能绕过 Cloudflare 的构建队列。但必须先在本地 build 并验证,因为你绕过了平台那道构建闸门。

为什么 curl 必须加 --noproxy '*'?

本机代理 127.0.0.1:7862 不稳定时,会把线上 200 伪装成 000 或 30 秒超时。不加这个参数,你会把网络问题当成站点挂了。

每周一张复习表

每周分享一张实用复习表,不收钱不打扰,想走随时走

邮箱存在 Cloudflare KV 里,只用来发每周更新;任何时候写信到hello@genwozuo.com说「退订」就删掉。详见隐私政策。

同方向继续

全部教程