61DH61DH
Home
Diary
English
Tools
Photography
Health
Tech
Home
Diary
English
Tools
Photography
Health
Tech
  • 日记

    • 前言
    • 搬家到 Cloudflare
    • Best Buy 与我的电器店记忆:从 2001 到今天的一次“退货又下单”
    • 中国流量异常日记
    • Coffee Sleeve 是什麼?
    • Node.js、nvm、Corepack 与 pnpm 环境说明
    • VuePress v2 index.scss 覆盖问题笔记
    • 回国礼物推荐:清单与避坑指南
    • 我的 iPhone 17 Pro 首日开箱记
    • 厨房装修小记:岛台移除后的地板方案
    • 一次 Maker 升级到 SKY 的实操:从 Coinbase 到 MetaMask,再谈钱包安全
    • 从“骨瘤?”到“脂肪瘤”:我的第一次手术日记
    • VS Code 中 Markdown 粘贴图片工作流(VuePress)
    • Perplexity 是流氓软件吗?– 一个技术站长的实录与更正
    • pnpm 10 也可以管理项目指定的 pnpm 版本
    • 装修的故事一 · 选柜子
    • 装修的故事二 · 卫生间
    • 装修故事 3|厨房
    • Scraper(爬虫)异常流量排查与处理记录
    • Skyoo「脑力素」广告很火,但靠谱吗?
    • 康师傅酸梅汤:异乡小记
    • 升级笔记:VuePress 从 2.0.0-beta.51 到 ^2.0.0-rc.24
    • 给 VuePress 添加评论系统:Waline 实战指南
    • Windows MongoDB Restore 性能排查记录
    • 讨好 Google,不是一件容易的事
    • 苹果 2025 发布会小记
    • 旧日记
2026/11/11

搬家到 Cloudflare

这次把 61DH 的 VuePress 静态网站从自己的服务器迁到 Cloudflare,顺手记录部署步骤和踩过的坑,方便以后参考。

1. 这个网站需要什么运行环境?

文章用 Markdown 写,VuePress 在构建时生成 HTML、CSS 和 JavaScript:

Markdown → VuePress build → docs/.vuepress/dist → 静态托管

Node.js 是构建时需要的工具,访问生成后的文章不需要运行 Node.js 服务。

原来的 deploy.sh 先执行 php genIndex.php 生成英语文章索引,再执行 npm run build,最后通过 scp 上传生成文件到服务器。现在改用 Cloudflare 从 Git 仓库自动构建和部署。

2. 我这次用的是 Workers

Cloudflare Pages 可以托管静态网站,Workers 也可以通过 Static Assets 托管。这次进入的创建页面有 Build command 和 Deploy command,使用的是 Workers 的部署流程。

连接 GitHub 仓库 deniapps/61dh,配置如下:

项目设置
Project name61dh
项目根目录仓库根目录
Build commandnpm run build
Deploy commandnpx wrangler deploy --assets ./docs/.vuepress/dist
Preview builds初次部署先关闭

Cloudflare 会安装依赖,然后执行构建和部署。这里不用运行原来的 deploy.sh。

3. 添加 Wrangler 配置

仓库根目录需要提交 wrangler.jsonc:

{
  "$schema": "node_modules/wrangler/config-schema.json",
  "name": "61dh",
  "compatibility_date": "2026-11-10",
  "assets": {
    "directory": "./docs/.vuepress/dist"
  }
}

name 与 Cloudflare 上的 Worker 名称一致,assets.directory 指向 VuePress 的构建结果。配置了目录后,部署命令也可以简化为 npx wrangler deploy。

compatibility_date 用来确定 Workers 的兼容行为,不是文章日期,也不用每次发布都修改。第一次部署缺少这个字段,构建虽然通过了,上传时仍然报错:

A compatibility_date is required when uploading a Worker.

所以要同时确认 Build command completed 和部署成功,不能只看 VuePress build 成功。

4. 图片在本地,为什么 Cloudflare 找不到?

第一次构建报错:

Rollup failed to resolve import "/uploads/2025-09-09-17-07-12.png"

原因是 .gitignore 原来有一行 uploads,把 docs/.vuepress/public/uploads 也忽略了。本地有图片,但 Cloudflare 克隆仓库后没有这些文件。

保留原来的忽略规则,并给网站公共图片目录加例外:

uploads
!docs/.vuepress/public/uploads/
!docs/.vuepress/public/uploads/**

然后把图片一起提交:

git add .gitignore docs/.vuepress/public/uploads
git commit -m "Include public uploads for Cloudflare builds"
git push

这类错误要先检查资源有没有进入 Git,不能只确认本地路径存在。

5. 绑定 61dh.com

部署成功后,先打开 Worker 提供的 workers.dev 地址,检查首页、文章和图片,再切换正式域名。

在 Cloudflare 控制台中:

  1. 打开 Workers & Pages → 61dh。
  2. 进入 Settings → Domains & Routes。
  3. 点击 Add → Custom Domain。
  4. 输入 61dh.com,不加 https://,也不加路径。
  5. 确认后等待域名和 HTTPS 证书生效。

前提是 61dh.com 已经作为有效的域名区域加入同一个 Cloudflare 账户。我选择统一使用不带 www 的地址,www.61dh.com 通过下面的规则跳转到根域名。

已有 DNS 记录的冲突

添加时遇到了:

Hostname '61dh.com' already has externally managed DNS records
(A, CNAME, etc). Delete them first or try a different hostname.

这里的 externally managed 表示已有记录不是由这个 Worker 的 Custom Domain 管理,不一定表示 DNS 在 Cloudflare 之外。

之前使用 Pages 时,设置流程处理了 DNS 更新;这次 Workers 的 Custom Domain 流程拒绝覆盖现有记录,需要先手动处理冲突。

操作步骤:

  1. 进入 61dh.com → DNS → Records。
  2. 先记录指向旧服务器的根域名记录类型、值和代理状态,方便必要时恢复。
  3. 删除与 61dh.com 冲突的根域名 A、AAAA 或 CNAME 记录;根域名可能显示为 @。
  4. 回到 Worker,再次添加 61dh.com 作为 Custom Domain。

Cloudflare 会为 Custom Domain 管理 DNS 和证书。删除旧记录到绑定完成之间可能有短暂中断,所以确认新站能访问后再操作。

只处理这次迁移的主机名。保留 MX、TXT、comments.61dh.com 和其他子域名记录。

把 www 跳转到非 www

最终希望的行为是:

https://www.61dh.com/diary/example.html?a=1
→ https://61dh.com/diary/example.html?a=1

DNS 的 CNAME 只处理域名解析,不会让浏览器自动修改地址。Workers Custom Domain 又是按请求的主机名匹配,所以只配置 www → 61dh.com 的 CNAME,还不能完成跳转。

配置步骤:

  1. 保持 61dh.com 绑定到 Worker 61dh。
  2. 在 DNS → Records 中,把 www 配置为指向 61dh.com 的 CNAME,并开启 Proxied(橙色云朵)。
  3. 进入 Rules → Redirect Rules → Create rule;如果有 Redirect from WWW to root 模板,可以直接使用。
  4. 匹配主机名 www.61dh.com,目标使用 https://61dh.com 并保留原路径,状态码选择 301,开启 Preserve query string。
  5. 部署规则,访问带路径和查询参数的 www 地址,确认浏览器跳转后路径和参数都保留。

如果手动配置规则,匹配表达式可以写成:

(http.host eq "www.61dh.com")

目标 URL 选择 Dynamic,使用表达式:

concat("https://61dh.com", http.request.uri.path)

查询参数由 Preserve query string 单独保留。这个方案不需要把 www.61dh.com 再添加为 Worker Custom Domain;跳转由 Cloudflare 的 Redirect Rule 处理。

6. PHP 和评论服务要单独考虑

php genIndex.php 是构建前的索引生成工具。当前 npm run build 不包含这一步,所以需要在本地运行并提交更新后的 Markdown:

php genIndex.php

如果以后希望完全自动化,可以把索引生成逻辑改成 Node.js,并加入构建流程。另外,该脚本按文件修改时间排序;Git checkout 后的修改时间不一定等于文章发布时间。

网站还有 quiz.html 调用 quiz_api.php。Workers Static Assets 不会执行 PHP,这个功能需要改成静态 JSON、Workers API,或者继续请求单独托管的 PHP 服务。

评论使用的是 Waline:https://comments.61dh.com。迁移文章的静态托管不会迁移 Waline 后端,评论域名继续指向原来的评论服务。

7. 以后如何更新文章

  1. 新增或修改 Markdown,图片放入 docs/.vuepress/public/uploads/。
  2. 如果英语文章索引有变化,在本地执行 php genIndex.php。
  3. 本地执行 npm run build 检查。
  4. 提交文章、图片及生成的索引,推送到 Cloudflare 配置的生产分支。
  5. 检查 Cloudflare 的构建和部署结果,再打开正式域名确认。

原来的 scp 上传步骤已经注释掉。以后发布主要靠 Git push 触发自动部署。

参考

  • Workers Static Assets 入门
  • Workers Builds 配置
  • Workers Custom Domains
Last Updated: 11/11/26, 3:24 PM
Contributors: Adam C
Prev
前言
Next
Best Buy 与我的电器店记忆:从 2001 到今天的一次“退货又下单”