01从零到上线,五步
以一个 Vite 前端 App 为例。第一次搭大约半小时,之后每次发布就是一次 git push。
本地建项目
用脚手架生成项目骨架,本地先跑通再说后面的事。
npm create vite@latest my-app -- --template react
cd my-app
npm install
npm run dev # 本地预览,确认能跑
推到 GitHub
代码托管到 GitHub,流水线就挂在仓库上。注意把 package-lock.json 一起提交——云端靠它精确还原依赖。
git init git add . git commit -m "init" gh repo create my-app --public --source=. --push
写流水线文件
在仓库里新建 .github/workflows/deploy.yml,告诉 GitHub Actions:什么时候触发、在云端按什么顺序干活。不用手写——下一节的生成器选好选项就能直接下载。
接上 Cloudflare Pages
两种接法任选:让 Pages 直接连 GitHub 仓库自动构建(零配置、最省事),或者由 GitHub Actions 构建完再用 wrangler 推给 Pages(控制权全在自己手里)。细节见第三节。
绑定自己的域名
把域名绑到 Pages 项目上,之后每次 push 都是给这个域名更新版本。像 mu2.is-a.bot 这样的子域名、以及在 Cloudflare 注册满 30 天的域名,都可以走这一步。
02流水线配置生成器
选好项目类型和部署目标,下面实时生成一份可用的 deploy.yml。复制或下载后放进仓库的 .github/workflows/ 目录即可。
生成之后还要做三件事
03Cloudflare 部署与绑域名
Cloudflare Pages 免费版每月有 500 次构建额度,个人项目绰绰有余。两种接法选一种就行,别混用。
接法一:Pages 直连 GitHub(最省事)
Cloudflare 控制台 → Workers & Pages → Create → Pages → Connect to Git,选中仓库,再按第四节的预设表填好「构建命令」和「输出目录」,保存。此后每次 push,Pages 自己拉代码、构建、发布,仓库里连 workflow 文件都不用放。
适合:纯前端项目、想最快上线。代价是构建过程在 Cloudflare 那边,流水线细节(多一步测试、构建后处理)不如 Actions 灵活。
接法二:GitHub Actions 构建 + wrangler 部署(本页生成器用的就是这个)
构建和测试都在 GitHub Actions 里跑,最后一步用 cloudflare/wrangler-action 把产物推到 Pages。需要在仓库的 Settings → Secrets and variables → Actions 里加两个密钥:
CLOUDFLARE_API_TOKEN # Cloudflare 控制台 → 头像 → My Profile → API Tokens 创建,权限选 Cloudflare Pages: Edit CLOUDFLARE_ACCOUNT_ID # Cloudflare 控制台首页右侧或域名概览页可见
适合:要在部署前跑测试、一个仓库发多个目标、或者想把发布流程完全版本化管起来。
绑定自定义域名
Pages 项目 → Custom domains → Set up a custom domain,输入要绑的域名:
· 域名就在同一个 Cloudflare 账号里(比如在 Cloudflare 注册、已满 30 天的域名):Cloudflare 自动添加 CNAME 记录,什么都不用手动配,等几分钟证书签发完,HTTPS 自动开启。
· 像 mu2.is-a.bot 这样的外部子域名:先在 is-a.bot 的申请里把记录指到本站的 pages.dev 地址(CNAME),或拿到 NS 托管后把子域名作为站点加进 Cloudflare,再回到 Pages 里绑定。
绑定完成后,git push 更新的就是这个域名上的内容,pages.dev 地址会继续作为预览入口保留。
04框架预设速查
在 Cloudflare Pages 里新建项目时要填的两个值。填错输出目录是新手最常见的翻车点——构建全绿,打开却是 404。
Vite(React / Vue)
- 构建命令
- npm run build
- 输出目录
- dist
Create React App
- 构建命令
- npm run build
- 输出目录
- build
Next.js(静态导出)
- 构建命令
- npm run build
- 输出目录
- out
Hugo
- 构建命令
- hugo --minify
- 输出目录
- public
Flutter Web
- 构建命令
- flutter build web
- 输出目录
- build/web
纯静态站点
- 构建命令
- (留空,不构建)
- 输出目录
- /(仓库根目录)
05排错速查
流水线红了先别慌,按这个顺序对:十次里有九次是下面这几样。
本地能跑,CI 里构建失败
最常见是版本不一致:CI 用了和本地不同的 Node 版本,老依赖在新版本上装不上,或者反过来。在 workflow 里用 actions/setup-node 锁死版本,仓库里再放一个 .nvmrc 写上同样的版本号,本地和云端就对齐了。
其次是大小写:本地 Windows/macOS 文件名不分大小写,Linux 云端分——import './Header' 和实际文件 header.jsx 对不上,本地没事、CI 直接报模块找不到。
npm ci 报错,说 lockfile 对不上
npm ci 要求 package.json 和 package-lock.json 严格一致。本地改了依赖却没把 lockfile 提交上去,CI 就会在这里停下。把 lockfile 加进 git 再推一次即可;以后每次 npm install 完记得连 lockfile 一起提交。
部署成功,但打开是 404 或白屏
先查输出目录:对照第四节的预设表,Vite 是 dist、CRA 是 build,填反了 Pages 发布的其实是空目录或源码目录。
如果是单页应用(React Router 这类),刷新子路由 404 是另一回事:在输出目录里加一个 _redirects 文件,内容写一行 /* /index.html 200,让所有路径都回到入口页交给前端路由处理。
环境变量在构建时读不到
Pages 的变量分「生产」和「预览」两套环境,填错一套就读不到;而且改完变量必须重新部署才生效,不会 retroactively 应用到已经构建好的版本。
前端项目还有一层:变量是在构建时被写进打包产物的(比如 Vite 的 VITE_ 前缀变量),运行时改服务器变量没有用。凡是打进前端产物的值都等于公开信息,别把真正的密钥放进去——密钥只放 CI 的 Secrets 和后端。
定时任务(schedule)没有准时跑
GitHub Actions 的 schedule 触发在高峰期会排队,免费仓库延迟几十分钟到数小时都出现过,整点尤其挤。两个应对:一是把 cron 时间往后错开整点、给任务留足余量;二是任务逻辑里判断「今天该做的事做没做」,而不是死等某个精确时间点——比如按日期检查产物是否存在,缺了才补跑。
构建额度或队列不够用
Cloudflare Pages 免费版每月 500 次构建、同时只能跑 1 个构建。频繁 push 的 monorepo 容易撞上:可以在 Pages 的构建设置里关掉预览部署(只构建生产分支),或者在 workflow 里给文档类改动加 paths-ignore,不触发无谓的构建。