一、目录结构
整个站点只有这几类文件,没有隐藏的构建产物:
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/ 自动生成索引
用 .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。
三、新增一篇文章
三步,五分钟:
- 复制
posts/里任意一个文件,改名成新的 slug(例如my-new-post.html)。 - 替换里面的标题、日期、分类、正文。正文直接写在
<article class="post-body">里,用常规的h2/h3/p/ul/pre/table标签;目录和阅读进度会自动生成。 - 在
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 能直接访问。整条链路免费。
已完成:域名已托管到 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.org → DNS → 添加记录:
| 字段 | 填什么 |
|---|---|
| 类型 | 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 & Pages → Create → Pages → Connect to Git。
- 选中刚才的仓库。
- 构建配置:Framework preset 选
None,Build 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 是 magali 和 fred 这一对。Cloudflare 给每个账号分配的 NS 名字是固定的——如果你在自己账号里看到的不是这两个名字,说明域名托管在另一个 Cloudflare 账号下,必须切到那个账号去建 Pages 和绑域名,否则绑定不会生效。
第 4 步:绑定自定义域名
- 回到 Pages 项目 → Custom domains → Set 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 . 会把站点目录里的文件全部上传,包括点开头的隐藏文件。这一点务必记住。
一、_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,脚本生成 | 免费 |
| 站内搜索增强 | 文章多了之后换成预生成倒排索引 | 免费 |