☁️ Cloudflare Pages 部署指南
本站(NotebookAI)使用 Cloudflare Pages 托管由 Quartz 5 生成的静态站点。本文记录实际部署流程、配置项和踩坑。
🎯 为什么选 Cloudflare Pages
| 对比项 | Cloudflare Pages | GitHub Pages |
|---|---|---|
| 构建环境 | 自带 CI,无需 GitHub Actions | 需要自己写 workflow |
| 全球 CDN | 默认开启,国内访问快 | 无 CDN,国内慢 |
| 自定义域名 | 免费,自动续 SSL | 免费,需手动配 |
| 构建限制 | 每月 500 次免费构建 | 每周 10 次限制 |
| 输出目录 | 任意路径 | 必须是仓库根或 docs/ |
🛠️ 1. 创建 Pages 项目
📍 入口位置(2026-10 实测):Cloudflare 已把 Pages 合并进「Workers & Pages」
统一界面,左侧菜单不再有独立的 Pages 条目,容易以为 Pages 被删了。其实还在,
只是被弱化。路径:左侧 Compute → Workers & Pages → 右上 Create application → 在选择器里选
Pages 标签 → Connect to Git⚠️ 同一个「Create application」入口里默认选中的是 Workers,它的配置界面是
Build / Deploy / Preview 三条命令,没有 Build output directory。那是Workers
Builds 的表单,需要wrangler.jsonc才能跑。纯静态站走 Pages,别选错。
- 登录 Cloudflare Dashboard
- 左侧菜单 → Compute → Workers & Pages
- 点 Create application → 选 Pages(不是 Workers)→ Connect to Git
- 选择 GitHub 仓库
lihuohuo1988/NotebookAI - 配置构建设置(见第 2 节)
⚙️ 2. 构建设置
| 项 | 值 |
|---|---|
| Production branch | main |
| Framework preset | None(静态站点) |
| Build command | cd .quartz && npm ci && node ../.scripts/sync-content.mjs && npx quartz build -d content |
| Build output directory | .quartz/public |
⚠️ 必须先跑同步脚本再 build,且必须带
-d content。
发布内容不是 vault 根,而是脚本复制出的.quartz/content/。漏掉同步脚本会
构建出空站;漏掉-d content会扫到错误的内容根。命令里的../.scripts/
是因为cd .quartz后才到 vault 根,注意有两个点。
环境变量
| 变量 | 值 | 说明 |
|---|---|---|
NODE_VERSION | 22.16.0 | 与 .quartz/.node-version 一致。不设会跟随 Cloudflare 默认版本,和本地 Node 24 存在偏差 |
NPM_VERSION | 可选 | npm 版本,建议 >=10.9.2 |
Root directory
留空(默认仓库根)。本站的 .quartz/ 和 .scripts/ 都在仓库根下,无需改成子目录。
🌐 3. 自定义域名
部署完成后,Pages 会分配一个默认域名 <项目名>.pages.dev。
添加自定义域名
- Pages 项目 → Custom domains → Set up a custom domain
- 输入域名,例如
notebookai.example.com - Cloudflare 会给出 CNAME 记录,去域名 DNS 处添加:
CNAME notebookai.example.com → <项目名>.pages.dev
- 等待 DNS 传播(通常几分钟到几小时)
- Cloudflare 自动申请并续期 SSL 证书,无需手动操作
⚠️ 域名的 NS 必须托管在 Cloudflare。Pages 与 Workers 都不支持把 NS 指向别家
的域名直接接管——那种情况只能在 DNS 服务商处加一条 CNAME 指向
notebookai-clq.pages.dev,但不会自动签发SSL,得自己配证书。
⚠️ 坑:DNS 记录类型
- 根域名(
example.com):必须用 CNAME Flattening(Cloudflare DNS 自动支持) - 子域名(
www.example.com):直接 CNAME 即可 - 如果 DNS 服务商不是 Cloudflare,根域名需要用 A 记录指向 Pages 的 IP
🔄 4. 自动部署
连接 GitHub 后,每次 push 到 main 分支自动触发构建。无需 GitHub Actions。
构建日志
Pages 项目 → Deployments → 点击某次部署查看日志。常见失败原因:
npm ci失败:package-lock.json与package.json不一致- 构建超时:默认 20 分钟,大站点可能不够
- 输出目录为空:检查
Build output directory是否正确
🔗 5. 与 Quartz 的关联
本站使用 Quartz 5 生成静态站点,Quartz 仓库克隆在 .quartz/ 目录内。相关笔记:
- Quartz 5 配置指南 — Quartz 安装、配置、插件、构建命令详解
- 模板说明 — vault 字段约定与
type词表
关键配置
quartz.config.yaml 中的部署相关配置:
configuration:
baseUrl: notebookai.example.com # ← 占位符,待回填为 notebookai-clq.pages.dev
enableSPA: true # ← 已开启,见下方说明
ignorePatterns: [] # ← 刻意留空,发布范围由同步脚本决定
fontOrigin: googleFonts # ← 国内访问建议改 local关于 enableSPA
早期本站设 enableSPA: false,原因是 SPA 路由与 explorer 插件定位当前页时的
scrollIntoView 冲突,会连带滚动整篇文档。该问题已修复(上游改用
getElementById 定位,冷加载下行为可接受),配套的 scrollIntoView 猴补丁
也已删除。现在 enableSPA: true,站点是 SPA,页面切换不重新加载。
「设false 会导致整站资源 404」是当时的错误结论,已作废。
关于 ignorePatterns
留空是有意的。发布范围由 .scripts/sync-content.mjs 顶部的 CONFIG.includeDirs
决定(白名单:笔记 / 附件 / 收件箱),复制方案下 .quartz/、openspec/
等仓库内部目录已不在内容树内,无需再靠 ignorePatterns 挡。
✅ 6. 线上实测(2026-10-02 首次部署)
站点:https://notebookai-clq.pages.dev
| 检查项 | 结果 |
|---|---|
首页 / | 200,67418 字节 |
| 笔记子页 | 200 |
| CSS / JS 资源 | 200(index-bb6c1746.css 等带hash 的文件名) |
| 子页相对路径 | ../index-*.css 正确回退一级 |
| 根路径 | 直接可用,无需重定向 |
| 不存在的路径 | 正常 404 |
| 表格时间列 | 2026-10-02 08:10:29,无毫秒、无 UTC 偏移 |
根路径 404 已解决:同步脚本复制时把 首页.md 改名成 index.md,Quartz 的
simplifySlug() 剥掉 index 后缀,slug 变成空串,URL 就是 /。不需要配重定向。
尾斜杠 URL 返回 308:/笔记/xxx/ 会被 Pages 重定向到无尾斜杠形式。实测资源
仍能正常加载(首页 CSS 200),但这是 Quartz 5 的已知缺陷——重定向后的路径如果资源
前缀算错会掉样式,详见下方警告。
⚠️ 7. 已知问题
baseUrl仍是占位符:线上 HTML 里能搜到notebookai.example.com,
sitemap、RSS、og:url/twitter:url全指向假域名- Google Fonts 国内被墙:
fontOrigin: googleFonts在国内加载失败,建议改local - 构建超时:大型 vault 可能超过 20 分钟构建限制
📋 8. 待办
- 回填
baseUrl为notebookai-clq.pages.dev(改quartz.config.yaml后需重新 push) -
fontOrigin改为local(权衡字体变化) - 配自定义域名(域名 DNS 须托管在 Cloudflare,Workers/Pages 不支持外部 NS 的域名)
- 手动验证带尾斜杠 URL 是否掉样式
⚠️ 不要配置「自动补尾斜杠」的重写/重定向规则。
Quartz v5.0.0 的emitPage()用baseDir = pathToRoot(slug)生成资源前缀,
按「段数 − 1」算..。这对无尾斜杠 URL(/笔记/xxx)是正确的,但对带尾斜杠
URL(/笔记/xxx/)会少退一级,导致../index.css解析成/笔记/index.css
而 404,整页掉样式。构建产物本身不产生尾斜杠链接,所以只要平台不做尾斜杠
规范化就不会触发。这条坑与
enableSPA无关——曾经误记为「enableSPA: true导致全站破版」
并据此关掉了 SPA,那个因果链不成立,SPA 已恢复true。完整推导见
Quartz 5 配置指南 坑 1。
🔗 相关
- Quartz 5 配置指南 — Quartz 安装、配置、插件、构建命令详解
- GitHub Pages 部署指南 — 备选部署方案
- Cloudflare Pages 文档
- Quartz 官方文档