Back to Journal
02 / Entry· 11 min read

白嫖 Cloudflare 跑自己的博客:国内用户保姆级教程

从注册账号、改造站点、双线部署到迁移域名 NS,一步步把博客搬到 Cloudflare Pages:免备案、零服务器成本、流量不限,以及大陆访问速度的真实预期与优化手段

🔊 系统朗读

我这个博客跑在一台腾讯云上——每月按时续费,平时访问量还没爬虫多。其实对个人静态博客来说,服务器这笔钱完全可以省掉:把站搬到 Cloudflare Pages 上,托管免费、流量免费、证书免费、免备案,唯一躲不掉的开销是域名本身。

但这只是一条路。如果你和我一样看重大陆访问速度、又不舍得退掉已经备案的腾讯云,那就反过来走双线并行:腾讯云当国内快线、Cloudflare 当境外兜底,同一个域名用 DNS 智能解析分流,两端都上 HTTPS,一条挂了秒切另一条。前 4 步讲纯 CF 迁移,后面「进阶落地」讲双线并行,你按自己的情况二选一 —— 本站实际采用的是双线并行

这篇文章就是我实际走一遍的完整记录,以本站(React + Vite 构建、GitHub Actions 部署、域名 lglg.xyz)为例。照着做,半小时内你的博客就能跑在 Cloudflare 上。

先看结论:到底要花多少钱

项目费用说明
Cloudflare Pages 托管¥0静态站带宽和请求数无限量免费
HTTPS 证书¥0Universal SSL 自动签发、自动续期
DNS 解析¥0顺手还把解析也升级了
域名已有域名新增 ¥0没有域名的话,.xyz / .top 首年几块到几十块
合计¥0 ~ 每年几十块域名续费

上面是按「纯 CF 迁移」算的账(服务器全退)。要是走双线并行,服务器钱得算回来——已备案的腾讯云轻量那台一般几十几百块/年,换来的是大陆访问几乎秒开,这是纯 CF 免费方案给不了的。

大陆用户用 CF 之前,先认清五个事实

这五条决定了后面每一步怎么做,先看懂再动手:

  1. CF 免费版没有中国大陆节点。大陆访客的请求会绕行海外入口(一般是美西),延迟约 150~250ms。想用国内节点?企业版专属,还要备案,个人别想。
  2. *.pages.dev*.workers.dev 在大陆基本被墙。"部署完送你一个免费域名"对国内访客毫无意义,所以必须绑自己的域名,这是整个教程的关键一步。
  3. 不需要备案。备案只在你把服务器放在中国大陆时才需要。域名在国内注册商买的、解析到海外 CF,完全不用备案。
  4. 注册不需要信用卡。免费套餐全程零支付信息,控制台还有简体中文。
  5. 静态博客是最适合 CF 的场景。Pages 对静态资源不限流量不限请求,个人博客一辈子用不完额度。
访问链路架构图:大陆访客经自定义域名、Cloudflare 边缘节点到达 Pages
访问链路架构图:大陆访客经自定义域名、Cloudflare 边缘节点到达 Pages

第一步:注册账号(3 分钟)

  1. 打开 https://dash.cloudflare.com/sign-up,邮箱 + 密码注册(Gmail、Outlook、QQ 邮箱都行),去邮箱点验证链接;
  2. 登录后右上角头像 → 语言切到「简体中文」,后文的菜单名都按中文界面写。

第二步:把站点改成"适合 CF"的样子

三处小改动,都是我踩过或差点踩的坑。

改动一:新建 public/_redirects(必做)

站点用的是 React Router 的 BrowserRouter。Pages 上如果有人直接打开一个没被预渲染过的路径(比如别人分享给你的深链),会直接 404。加这个文件让所有未知路径回退到 index.html

/*    /index.html    200

改动二:SITE_URL 换成 https

上 CF 后全站强制 HTTPS,RSS 和 sitemap 里生成的链接也得跟着变,不然订阅器拉不到:

ts
const SITE_URL = 'https://www.lglg.xyz'

改动三:处理 Google Fonts(大陆访客强烈建议)

index.html 里引了 fonts.googleapis.com——这个域名在大陆是被墙的。后果是:大陆用户首次访问时浏览器会卡在这个请求直到超时,首屏白屏好几秒;Service Worker 只能缓存成功过的响应,第一次失败就永远没得缓存。

两个方案选一:

  • 方案 A(最简单):删掉字体 <link>,改用系统字体栈兜底(PingFang SC / Microsoft YaHei),观感损失很小;
  • 方案 B(保留设计感):下载 Inter 和 Noto Sans SC 的 woff2 子集放进 public/fonts/,改用本地 @font-face。workbox 的 globPatterns 里本来就有 woff2,SW 会自动缓存,字体跟站同源同速。

本地验证一下构建产物:

bash
pnpm build && pnpm preview

dist/ 目录就是交给 CF 的全部东西。

第三步:部署——两种方式任选

方式 A:网页点点点(零命令行)

  1. 控制台左侧 → Workers 和 Pages创建应用程序 → 切到 Pages 标签 → 连接到 Git

  2. 授权 GitHub,选中仓库 → 开始设置;

  3. 构建配置:

    配置项
    Framework presetVite
    Build commandpnpm build
    Build output directorydist
  4. 环境变量加两条,否则 pnpm 项目会出幺蛾子:

    NODE_VERSION = 20
    PNPM_VERSION = 9    # 与 lockfile 大版本一致
    
  5. 保存并部署,两三分钟后你会得到一个 xxx.pages.dev 地址。之后每次 push 自动部署,开 PR 还有独立预览地址。

⚠️ 方式 A 有个代价:CF 的构建机上没有 Chrome,Puppeteer 预渲染会被优雅跳过。站点照常上线,只是少了 SEO 预渲染 HTML。想保住预渲染,看方式 B。

方式 B:沿用 GitHub Actions(推荐 ⭐)

理由很实际:GitHub 的 ubuntu-latest 自带 Chrome,预渲染不会丢;而且和现有「打 tag 触发」的习惯完全一致,还能和腾讯云双线并行跑一段时间再切换。

部署流水线:一次 git push,腾讯云与 Cloudflare 双线同时上线
部署流水线:一次 git push,腾讯云与 Cloudflare 双线同时上线

操作步骤:

  1. 拿 API Token:CF 控制台 → 头像 → 我的个人资料 → API 令牌 → 创建令牌 → 用「编辑 Cloudflare Workers」模板;
  2. 拿 Account ID:任意域名的概述页右下角复制;
  3. GitHub 仓库 → Settings → Secrets and variables → Actions,新增两个 secret:CLOUDFLARE_API_TOKENCLOUDFLARE_ACCOUNT_ID
  4. 先在网页上占住项目名:Workers 和 Pages → 创建 Pages → 直接上传,项目名叫 my-site,随便传个文件完成创建(CI 非交互模式没法自动建项目,这步是给它占位);
  5. deploy.yml 里追加一个 job:
yaml
  deploy-cloudflare:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: pnpm/action-setup@v4
        with:
          version: 9            # 与 lockfile 大版本一致
      - uses: actions/setup-node@v4
        with:
          node-version: 20
          cache: pnpm
      - run: pnpm install --frozen-lockfile
      - run: pnpm build         # ubuntu-latest 自带 Chrome,预渲染不跳过
      - uses: cloudflare/wrangler-action@v3
        with:
          apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}
          accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
          command: pages deploy dist --project-name=my-site --branch=main
  1. 打一个 publish-test tag 推上去,Actions 里看到新旧两个 job 都绿了,双线部署就成了。

第四步:绑定自己的域名(关键一步)

域名是在国内注册商买的也没问题,流程如下:

  1. CF 首页 → 添加域 → 输入 lglg.xyz → 选 Free 免费计划
  2. CF 会扫描现有 DNS 记录让你确认——检查一遍 www 等记录都在(换 NS 后旧解析就不生效了,缺的要在 CF 里补齐);
  3. CF 给你两个 nameserver 地址(形如 aaa.ns.cloudflare.com);
  4. 回腾讯云控制台 → 域名管理 → 修改 DNS 服务器(注意:是改"DNS 服务器",不是加解析记录!)→ 换成 CF 给的那两个;
  5. 回 CF 点「检查名称服务器」。.xyz 一般几分钟到几小时生效,状态变成「活动」即可;
  6. 进 Pages 项目 → 自定义域 → 分别添加 www.lglg.xyz 和裸域 lglg.xyz。CF 会自动建 CNAME 记录并签发证书,不用手动申请证书
  7. SSL/TLS → 边缘证书 → 打开始终使用 HTTPS
  8. 等 DNS 全球生效(通常半小时内),https://www.lglg.xyz 就跑在 Cloudflare 上了 🎉

还没有域名的话:只用支付宝就在腾讯云/阿里云买(实名认证即可,无需备案);有 Visa/Mastercard/PayPal 可以直接用 Cloudflare Registrar,按成本价卖没有溢价,.com 约 $10/年。

进阶落地:国内主 + Cloudflare 备——双线并行(本站实战选用)

前面 4 步是「把站彻底搬到 CF」(免备案、省服务器)。但如果你跟我一样,腾讯云那台已经备案、也舍不得退,那性价比最高的其实是双线并行:腾讯云当国内快线、Cloudflare 当境外兜底,同一个域名,两端都上 HTTPS,一条线路挂了秒切另一条。这是我实际落地的拓扑:

双线拓扑图:同一域名国内走腾讯、境外走 Cloudflare
双线拓扑图:同一域名国内走腾讯、境外走 Cloudflare

适用前提(缺一不可)

  • ICP 备案:腾讯云那台是境内服务器,必须完成备案(第 3 步的部署方式 B 能推它,但备案得提前办好);
  • 一台已备案服务器 + 域名:域名最好就在腾讯云/阿里云买的,方便用它家的 DNS 做智能解析;
  • 接受「服务器 + 域名」两个固定成本:换来大陆访客几乎秒开,这是纯 CF 方案给不了的。

腾讯侧:acme.sh 自动续期 HTTPS(重点)

远端服务器的 HTTPS 全程零手工干预,靠 acme.sh 实现「自动申请、自动续期、续期后自动重载 nginx」。在服务器上照下面做:

  1. 装 acme.sh(一条命令,装到 ~/.acme.sh):

    bash
    curl https://get.acme.sh | sh -s email=you@example.com
    
  2. 用 webroot 模式给 www.lglg.xyz 签发证书(先保证 nginx 已把该域名指到静态目录,如 /var/www/blog):

    bash
    acme.sh --issue -d www.lglg.xyz -w /var/www/blog
    

    如果 nginx 里已经把 server_name 配好,也可以直接 --nginx 让 acme.sh 自动读配置签发。

  3. 把签好的证书装到 nginx 能读到的路径,并指定续期成功后执行的动作

    bash
    acme.sh --install-cert -d www.lglg.xyz \
      --key-file       /etc/nginx/ssl/lglg.xyz.key \
      --fullchain-file /etc/nginx/ssl/lglg.xyz.fullchain.cer \
      --reloadcmd      "nginx -s reload"
    

    这一步是自动续期的关键--reloadcmd 会被 acme.sh 记下来,每次续期成功都会自动执行 nginx -s reload,证书换了、配置重载,网站无感切换。

  4. nginx 站点配置(/etc/nginx/conf.d/lglg.xyz.conf)大概是这样:

    nginx
    server {
        listen 443 ssl http2;
        server_name www.lglg.xyz;
        ssl_certificate     /etc/nginx/ssl/lglg.xyz.fullchain.cer;
        ssl_certificate_key /etc/nginx/ssl/lglg.xyz.key;
        root /var/www/blog;
        index index.html;
        location / { try_files $uri $uri/ /index.html; }
    }
    server {
        listen 80;
        server_name www.lglg.xyz;
        return 301 https://$host$request_uri;
    }
    
  5. 确认自动续期已就位:acme.sh 安装时会自动写入一条每日 crontab,到期前约 30 天自动续期。验证一下:

    bash
    acme.sh --list             # 看证书与到期日
    crontab -l                 # 应能看到 ~/.acme.sh/acme.sh --cron 的定时任务
    acme.sh --cron --force     # 手动触发一次,确认续期与 reload 都正常
    

    到这里,腾讯侧的 HTTPS 自动续期已经闭环:申请 → 每日检查 → 到期前自动续 → nginx 自动重载,你什么都不用管。

Cloudflare 侧

跟前面纯 CF 方案完全一样:CF Pages 部署(方式 A 或 B)+ 绑定自定义域 + 打开「始终使用 HTTPS」。Universal SSL 自动签发自动续期,这条线的证书不用你操心。

DNS 智能/加权解析:同一域名怎么分流

两条线路都搭好后,靠 DNSPod 智能解析让「谁访问走哪条」。登录 DNSPod → 域名解析 → lglg.xyz,给同一个主机名按线路加多条记录:

  • 境内线路(默认 / 电信 / 联通 / 移动…)→ A 记录 → 腾讯云服务器公网 IP;
  • 境外线路CNAME 记录 → 你的 Cloudflare Pages 项目地址(形如 my-site.pages.dev)。

想要更精细,还能用加权解析:给同一条记录配权重做比例分流(例如境内 100%、境外 100%)。这样大陆访客天然被解析到腾讯云(直连最快),海外访客走 CF 全球网络,速度也很稳。

⚠️ 一个绕不开的约束:两种拓扑二选一

Cloudflare 要给 www.lglg.xyz 签发 Universal SSL,前提是这个域名的 NS 在 Cloudflare;而 DNSPod 要按「境内/境外」线路分流,前提是 NS 在 DNSPod。两件事只能选一个做权威 DNS,所以「双线」有两种可行拓扑:

拓扑谁做主 DNS大陆速度说明
A:CF 做权威 DNSCloudflare中等(免费版无国内节点)www 全走 CF,腾讯云只当源站/CDN 回源;不用额外备案折腾,但大陆仍「能用偏慢」
B:DNSPod 做智能解析DNSPod最快境内→腾讯、境外→CF;腾讯侧用 acme 证书,CF 侧给独立子域绑 Pages 项目拿 Universal SSL

我落地用的是拓扑 Bwww.lglg.xyz 走腾讯(acme 自动续期证书),再给 Cloudflare 单独绑个子域(如 global.lglg.xyz)指向 Pages 项目。这样两边都有合法 HTTPS、都能免费,大陆访问最快,境外由子域 → CF 兜底。.pages.dev 在大陆被墙,所以境外子域也一定得绑自己的自定义域——这一步跟文章第 4 步完全一样。

双线怎么互相兜底

  • 腾讯云挂了:把 DNSPod 里境内那条 A 记录临时改成指向 CF(或切到 CF 子域/源站),几分钟生效;
  • CF 那条被墙或异常:国内访客本来就走腾讯,不受影响;
  • 真要退腾讯:把 www 的 NS 迁回 CF 走拓扑 A,或把解析全指到腾讯子域,代码都不用动。

双线踩坑

  • 腾讯侧证书虽然自动续期,还是定期 acme.sh --list 看一眼到期日,用 --cron --force 测一遍续期流程更稳;
  • 境外子域绑 CF 后,记得在 CF 也对该子域打开「始终使用 HTTPS」,否则边缘可能回退 HTTP;
  • .pages.dev 大陆被墙,境外子域必须绑自定义域,光靠 pages.dev 地址对国内访客没意义;
  • PNPM 项目在 CF 构建要设 NODE_VERSION / PNPM_VERSION,否则方式 A 会报错(见第 3 步)。

免费额度一览(个人博客根本用不完)

服务免费额度
Pages500 次构建/月;带宽和请求数无限;单文件 ≤25MB,≤2 万文件
Workers(以后加动态 API)10 万次请求/天
R2 对象存储(做图床很香)10GB 存储,流出流量免费
Web Analytics免费、无 Cookie 的访问统计
Zero Trust Access50 用户免费,可给 /admin 加邮箱验证码保护

最后一条专门提醒:纯前端 admin 后台部署到公网后任何人都能打开 /admin 页面。去 Zero Trust 给 /admin* 路径套一个 Access 策略(邮箱 OTP 验证),五分钟配好,免费。

大陆速度优化阶梯(按性价比排序)

  1. 自有域名——上面已做,最大的一步;

  2. 字体本地化——不做的话首屏卡死比网络慢更致命;

  3. 图片压 WebP/AVIF,长图懒加载;

  4. 带 hash 的 js/css CF 默认边缘长缓存,HTML 不缓存保证更新即时生效,一般不用动;

  5. 进阶:优选 IP。三大运营商到 CF 不同 Anycast 入口的速度差异很大,用测速工具找出对自己网络最快的 CF IP,把解析从 CNAME 改成 A 记录直指它。效果明显,但 IP 可能失效要偶尔重测,属于折腾型玩法;

  6. 终极方案对比(如果以后受不了海外延迟):

    方案大陆速度备案成本
    纯 Cloudflare Pages中等,全球访客友好不需要≈¥0
    国内 OSS/CDN(腾讯 COS+CDN)必须备案几元~几十元/月
    双线:国内主 + CF 备最快需要两者之和
  7. 别幻想免费版开中国节点,那是企业版专属。

「双线」怎么真正落地(acme.sh 自动续期 + DNSPod 智能解析分流),我在上面的 「进阶落地」一节 写了完整步骤和两种拓扑,照着做就行。

你可能会踩的坑

部署完更新没生效? 先强刷(Ctrl/Cmd+Shift+R);autoUpdate 的 PWA 会自动换新,老用户下次打开即更新。

直接访问二级路径 404? _redirects 忘了建。

方式 A 构建报 tsc 错误? CF 构建机和本地环境略有差异,先本地跑通 pnpm build 再推。

RSS 里链接还是 http? SITE_URL 忘了改 https。

腾讯云那台要不要退? 别急着退。双线跑两周,用 Web Analytics 看看大陆访客的实际体验再决定;也可以留着当国内快线路,DNS 一条 CNAME 的事。

担心被墙牵连域名? CF 主站在大陆可正常访问,自有域名解析到 CF 目前稳定。真遇到极端情况,NS 十分钟切回 DNSPod 指向腾讯云——这正是留双线的意义。

行动清单

路线一(纯 CF 迁移)

  • 注册 CF 账号
  • public/_redirects、改 SITE_URL 为 https、处理 Google Fonts
  • 选部署方式(推荐 B:GitHub Actions + wrangler)
  • 迁移域名 NS 到 Cloudflare
  • Pages 绑定 www + 裸域,开强制 HTTPS

路线二(双线并行,本站采用)

  • 国内服务器先完成 ICP 备案
  • 腾讯侧用 acme.sh 配置 HTTPS 自动续期(见「进阶落地」)
  • CF Pages 绑定境外子域(如 global.lglg.xyz),开强制 HTTPS
  • DNSPod 按境内/境外线路智能(或加权)解析分流

两条路线都做

  • (可选)Zero Trust 保护 /admin
  • 跑两周,用 Web Analytics 看大陆访客实际体验,再决定退不退腾讯云

总结一句话:域名以外全免费、备案完全不需要,是「纯 CF 迁移」的最优解;想要大陆访问最快、又舍不得退已备案的服务器,就上「双线并行」——腾讯云当国内快线、Cloudflare 当境外兜底,两边都自动续期 HTTPS,进可攻退可守。 对一个访问量靠朋友圈的个人博客来说,按自己情况二选一,都能省钱又稳当。

分享
← 返回博客列表
🎁 有邀请福利哦,点击查看
🎁