目标域名mu2.is-a.bot

GIT PUSH → BUILD → DEPLOY

推一次代码,App 自动上线

做 App 最容易被低估的环节,是「发布」:手动打包、手动上传、改错一个文件就要重来一遍。 CI/CD 把这件事变成一条自动流水线——你只管往 GitHub 推代码,构建、测试、部署、绑域名全部自动完成, 几分钟后新版本就在 Cloudflare 的全球网络上跑起来了。

这一页是给自己留的实操手册:完整流程、一个能直接生成 GitHub Actions 配置的工具、Cloudflare Pages 的部署与绑域名步骤。 作者的博客站 knightblog.pages.dev 就跑在 Cloudflare Pages 上,本站的目标域名是 mu2.is-a.bot。

1
提交代码
git push 到 GitHub
2
安装依赖
云端干净环境拉取
3
自动测试
不过关就停在这里
4
构建打包
生成可部署的产物
5
自动部署
发布到 Cloudflare Pages
6
上线
自定义域名即时生效

整条流水线由仓库里一个 YAML 文件定义。常见规模的项目从 push 到上线约 1–3 分钟;任何一步失败,线上跑的仍然是上一个好版本,不会被推一半的坏代码污染。

01从零到上线,五步

以一个 Vite 前端 App 为例。第一次搭大约半小时,之后每次发布就是一次 git push。

1

本地建项目

用脚手架生成项目骨架,本地先跑通再说后面的事。

npm create vite@latest my-app -- --template react
cd my-app
npm install
npm run dev        # 本地预览,确认能跑
2

推到 GitHub

代码托管到 GitHub,流水线就挂在仓库上。注意把 package-lock.json 一起提交——云端靠它精确还原依赖。

git init
git add .
git commit -m "init"
gh repo create my-app --public --source=. --push
3

写流水线文件

在仓库里新建 .github/workflows/deploy.yml,告诉 GitHub Actions:什么时候触发、在云端按什么顺序干活。不用手写——下一节的生成器选好选项就能直接下载。

4

接上 Cloudflare Pages

两种接法任选:让 Pages 直接连 GitHub 仓库自动构建(零配置、最省事),或者由 GitHub Actions 构建完再用 wrangler 推给 Pages(控制权全在自己手里)。细节见第三节。

5

绑定自己的域名

把域名绑到 Pages 项目上,之后每次 push 都是给这个域名更新版本。像 mu2.is-a.bot 这样的子域名、以及在 Cloudflare 注册满 30 天的域名,都可以走这一步。

02流水线配置生成器

选好项目类型和部署目标,下面实时生成一份可用的 deploy.yml。复制或下载后放进仓库的 .github/workflows/ 目录即可。

Cloudflare Pages 的项目名,只用小写字母、数字和连字符。
推到这个分支才触发部署;另外保留了手动触发入口。
和本地版本保持一致,省得 CI 里出现「本地能跑、云端报错」。
文件路径:.github/workflows/deploy.yml

          

生成之后还要做三件事

    03Cloudflare 部署与绑域名

    Cloudflare Pages 免费版每月有 500 次构建额度,个人项目绰绰有余。两种接法选一种就行,别混用。

    A

    接法一:Pages 直连 GitHub(最省事)

    Cloudflare 控制台 → Workers & Pages → Create → Pages → Connect to Git,选中仓库,再按第四节的预设表填好「构建命令」和「输出目录」,保存。此后每次 push,Pages 自己拉代码、构建、发布,仓库里连 workflow 文件都不用放。

    适合:纯前端项目、想最快上线。代价是构建过程在 Cloudflare 那边,流水线细节(多一步测试、构建后处理)不如 Actions 灵活。

    B

    接法二: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 控制台首页右侧或域名概览页可见

    适合:要在部署前跑测试、一个仓库发多个目标、或者想把发布流程完全版本化管起来。

    C

    绑定自定义域名

    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,不触发无谓的构建。