返回首页
站点维护

写作与部署:这个博客是怎么跑起来的

一份给未来的自己看的操作手册。包括本地怎么预览、新文章怎么加、以及怎么绑定到 lslongabc.dpdns.org。

一、目录结构

整个站点只有这几类文件,没有隐藏的构建产物:

blog/
├── index.html            首页(文章列表 + 筛选 + 搜索)
├── archive.html          归档页(按年份时间线)
├── about.html            关于页
├── guide.html            本页
├── 404.html              404 页面
├── favicon.svg           站点图标
├── robots.txt            搜索引擎抓取声明
├── CNAME                 自定义域名(部署时用)
├── posts/                每篇文章一个 HTML 文件
├── assets/
│   ├── css/style.css     全部样式(设计令牌 + 组件)
│   ├── js/app.js         全部交互逻辑
│   └── data/posts.js     文章索引(唯一的内容清单)
└── tools/build-index.mjs 扫描 posts/ 自动生成索引
关于 posts.js 为什么不是 JSON

.js 挂一个全局数组,是为了让站点在 file:// 协议下也能直接双击打开预览。如果用 fetch() 读 JSON,浏览器会因为跨源策略拒绝加载,必须起服务器才行。

二、本地预览

方式 A:直接双击(最省事)

双击 index.html 就能看。列表、筛选、搜索、深色模式全部可用,因为索引是从 posts.js 同步加载的。

方式 B:起一个本地服务器(推荐)

路径干净,行为更接近线上环境。在 blog 目录下执行任意一条:

# Python 3
python -m http.server 4321

# Node.js
npx serve -l 4321

# PHP
php -S localhost:4321

然后浏览器打开 http://localhost:4321

三、新增一篇文章

三步,五分钟:

  1. 复制 posts/ 里任意一个文件,改名成新的 slug(例如 my-new-post.html)。
  2. 替换里面的标题、日期、分类、正文。正文直接写在 <article class="post-body"> 里,用常规的 h2/h3/p/ul/pre/table 标签;目录和阅读进度会自动生成。
  3. assets/data/posts.js 里加一条记录:
{
  slug: 'my-new-post',            // 必须和文件名一致(不含 .html)
  title: '文章标题',
  date: '2026-09-17',             // YYYY-MM-DD
  category: 'tech',               // tech | industry | reading | pixel
  tags: ['标签一', '标签二'],
  excerpt: '一两句话的摘要,会显示在首页卡片上。',
  minutes: 8,                     // 预估阅读分钟
  featured: false                 // true 会让卡片高亮(置顶感)
}
懒人做法

不想手写索引,就运行 node tools/build-index.mjs。它会扫描 posts/ 下所有 HTML,从每个文件的 <meta name="post:*"> 标签里读取元数据并重建 posts.js。约定见脚本头部注释。

四、正文里能直接用的小组件

样式都写好了,复制即用。

提示块

<div class="note">普通提示</div>
<div class="note tip">建议 / 经验</div>
<div class="note warn">注意事项</div>

表格

<table>
  <thead><tr><th>列一</th><th>列二</th></tr></thead>
  <tbody><tr><td>值</td><td>值</td></tr></tbody>
</table>

代码块(自带复制按钮)

<pre><code>你的代码</code></pre>

五、部署到 Cloudflare Pages

目标是 https://lslongabc.dpdns.org 能直接访问。整条链路免费。

当前状态(2026-09-17 实测)

已完成:域名已托管到 Cloudflare(NS = magali + fred,zone 状态 active);Pages 项目 blog 已创建;站点已部署上线,临时地址 https://blog-5jp.pages.dev;自定义域名 lslongabc.dpdns.org 已挂到项目上。

还差一步:域下缺一条 CNAME 记录,所以绑定处于 pending。原因是 wrangler 的登录凭据里有 pages:write 但没有 DNS 写权限,这一步它做不了。

补上最后那条 CNAME

Cloudflare 控制台 → 选中 lslongabc.dpdns.orgDNS添加记录

字段填什么
类型CNAME
名称@(代表 lslongabc.dpdns.org 本身)
目标blog-5jp.pages.dev
代理状态已代理(橙色云)

保存后 1~5 分钟证书签发完成,https://lslongabc.dpdns.org 即可访问。

想省掉手动操作

项目里有一个收尾脚本 tools/cf-domain.mjs,能自动检查并补上这条记录、然后轮询到生效。它需要一个带 Zone → DNS → Edit 权限的 API 令牌。

令牌要放在站点目录之外(例如 D:\workbuddy\2026-09-17-11-30-30\.cf-token),因为部署会把站点目录里的文件全部上传,放在里面等于把令牌公开。

放好后执行:node tools/cf-domain.mjs 或先看会做什么:node tools/cf-domain.mjs --dry

令牌用完随时可在 Cloudflare 控制台 Revoke。

方式 A:wrangler 直接上传(最快,不需要 GitHub)

三条命令上线。适合只想尽快把域名跑通的情况,本机需要有 Node.js。

cd blog

# 1) 登录 Cloudflare,会弹出浏览器授权
npx wrangler login

# 2) 首次部署,同时创建名为 blog 的 Pages 项目
npx wrangler pages deploy . --project-name=blog

执行完会输出一个 https://blog.pages.dev 之类的临时域名,先打开确认页面正常。

以后每次更新只需重复第二条:

npx wrangler pages deploy . --project-name=blog

方式 B:GitHub 自动部署(push 即上线)

适合长期写、想留版本历史的情况。配置一次,之后每次 git push 自动发布。

第 1 步:代码推到 GitHub

cd blog
git init
git add .
git commit -m "init blog"
git branch -M main
git remote add origin https://github.com/<你的用户名>/<仓库名>.git
git push -u origin main

第 2 步:Cloudflare Pages 建项目

  • 登录 Cloudflare 控制台 → Workers & PagesCreatePagesConnect to Git
  • 选中刚才的仓库。
  • 构建配置:Framework presetNoneBuild command 留空,Build output directory/(因为站点根目录就是仓库根目录)。
  • 保存并部署,几十秒后会得到一个 xxx.pages.dev 的临时域名,先访问确认没问题。

第 3 步(已完成):域名托管到 Cloudflare

这一步本次已经做完,写在这里仅供参考。万一哪天 NS 被改回去导致失效,按下面重做:

  • Cloudflare 控制台 → 添加站点 → 输入 lslongabc.dpdns.org → 选 Free 计划。
  • Cloudflare 会分配两个专属 NS 地址。
  • 回到 dpdns.org(DigitalPlat)管理面板,把这两个 NS 填到该域名的 Name Server 设置里,保存。
  • 等 3~10 分钟,Cloudflare 里域名状态变为活动即成功。
一个要核对的点

本次解析到的 NS 是 magalifred 这一对。Cloudflare 给每个账号分配的 NS 名字是固定的——如果你在自己账号里看到的不是这两个名字,说明域名托管在另一个 Cloudflare 账号下,必须切到那个账号去建 Pages 和绑域名,否则绑定不会生效。

第 4 步:绑定自定义域名

  • 回到 Pages 项目 → Custom domainsSet up a custom domain
  • 输入 lslongabc.dpdns.org,按提示确认。
  • 因为域名已托管在同一个 Cloudflare 账号下,CNAME 记录会自动创建,证书也会自动签发。
  • 等 1~5 分钟,https 访问即生效。
两个容易踩的坑

一、dpdns.org 域名一年一续,到期前 180 天内要回面板手动点续期,逾期会被回收。

二、如果 DNS 里已经存在一条 lslongabc 的 A 或 CNAME 记录,绑定自定义域名时会冲突,先把旧记录删掉再绑定。

六、日常更新流程

写完一篇文章后,先重建索引,再发布:

node tools/build-index.mjs

然后按你选的方式发布。

方式 A(wrangler):

npx wrangler pages deploy . --project-name=blog

方式 B(GitHub):

git add .
git commit -m "post: 新文章标题"
git push

方式 B 下 Cloudflare Pages 会自动检测到 push 并重新部署,通常 30 秒内生效,不需要手动上传任何文件。

三个会随部署一起生效的配置文件

_headers 控制响应头(安全头 + 全部内容不走强缓存)。

_redirects 控制转发规则,目前把 /tools/*/.cf-token/.env 转到 404 页,避免本地脚本和可能的密钥文件被公开访问。以后改了文章文件名,也可以在 _redirects 里加 301 保住老链接。

.gitignore 只管 Git,不管部署 —— wrangler pages deploy . 会把站点目录里的文件全部上传,包括点开头的隐藏文件。这一点务必记住。

Cloudflare Pages 的三个坑(都踩过了)

一、_redirects 不支持 404 状态码。只支持 200(改写)/301/302/303/307/308。写 404 会被静默忽略,看起来配了其实没生效。

二、.assetsignore 对 Pages 无效。那是 Workers 静态资源的机制,Pages 不认。

三、Pages 默认提供无扩展名 URL。访问 /posts/x.html 会 308 跳到 /posts/x,页面实际在无扩展名路径返回。所以 _headers 里用 /*.html 这类模式匹配不到,要写在 /* 下面。

七、还可以加什么

需求做法成本
评论接 Giscus(基于 GitHub Discussions)免费
访问统计Cloudflare Web Analytics免费、无 Cookie
RSS 订阅手写一个 feed.xml,脚本生成免费
站内搜索增强文章多了之后换成预生成倒排索引免费
#站点维护#Cloudflare#静态站点