B
← 返回文章列表
#Markdown

Markdown、D1、RSS 与站点地图:博客发布为什么要做四处一致性校验

6 分钟阅读系列 · 博客搭建 #5

Markdown、D1、RSS 与站点地图:博客发布为什么要做四处一致性校验

当博客同时使用仓库 Markdown、边缘数据库、RSS 和 sitemap 时,构建成功不代表文章真的上线。本文给出一套从内容源到生产回读的一致性发布方法。

一个现代博客可能同时有四个“文章存在”的判断来源:Git 仓库里的 Markdown、生产数据库中的文章记录、RSS feed,以及搜索引擎读取的 sitemap。

这四处只要有一处不同步,就会出现很迷惑的现象:代码已经提交,构建也成功,但文章页 404;首页能看到文章,RSS 却没有;浏览器能访问,搜索引擎却永远找不到。

四个表面分别负责什么

表面主要职责常见失败
Markdown可审查的内容源与 Git 历史frontmatter 错误、slug 冲突
D1 / SQLite生产运行时的数据查询migration 未打包或未执行
RSS订阅器的新文章发现缓存旧、过滤条件不同
sitemap搜索引擎的页面发现路径漏写、canonical 不一致

构建工具通常只保证代码能编译,不能保证这四个表面已经指向同一篇文章。

让 slug 成为稳定主键

文章标题可以调整,URL 最好保持稳定。可以用文件名生成 slug,并让 Markdown、数据库、RSS 和 sitemap 都引用同一个值:

content/posts/atomic-publishing.md
             ↓
slug = atomic-publishing
             ↓
/posts/atomic-publishing

数据库迁移使用 ON CONFLICT(slug) DO UPDATE,可以让重复部署变成幂等更新,而不是插入重复文章。

INSERT INTO posts (slug, title, content, date)
VALUES ('atomic-publishing', '原子发布', '...', '2026-08-24')
ON CONFLICT(slug) DO UPDATE SET
  title = excluded.title,
  content = excluded.content,
  date = excluded.date,
  updated_at = CURRENT_TIMESTAMP;

为什么迁移文件必须进入部署产物

本地仓库中存在 migration,不等于托管平台收到 migration。若打包过程只上传服务端 bundle 和静态资源,生产 Worker 能启动,但数据库里没有新文章。

因此产物检查至少要确认:

  • 服务端入口存在;
  • 托管元数据存在;
  • 静态资源完整;
  • 所有需要执行的 migration 位于平台约定目录;
  • .env、令牌和本地开发密钥没有被打包。

这一步检查的是“即将发布的包”,不能只检查源码目录。

构建成功不等于生产成功

一次可靠发布至少要经过三层证据:

1. 内容层

  • Markdown frontmatter 可解析;
  • slug、日期、标签和系列字段符合约定;
  • migration 与 Markdown 正文一致;
  • SQL 中的单引号等字符已正确转义。

2. 构建与数据层

  • 生产构建成功;
  • 本地空数据库能按顺序应用全部 migration;
  • 重复应用时不会制造重复记录;
  • 部署包包含数据库迁移且不含秘密文件。

3. 生产回读层

  • 文章 URL 返回 HTTP 200;
  • 页面包含本次文章的独特标题或 slug;
  • 数据库健康接口返回已配置且可查询;
  • RSS 返回 200 并包含新文章;
  • sitemap 返回 200 并包含同一 URL。

只有部署任务显示绿色,而没有做生产回读,最多只能说明“平台接受了这次部署”。

不要只验证首页

首页往往有缓存、静态兜底或来自 Markdown 的列表,因此它显示新标题并不能证明文章详情已经进入数据库。

反过来,文章详情页能访问,也不能证明 RSS 与 sitemap 已更新。四个表面应该分别检查,而且要用文章的唯一 slug 做断言。

Article HTTP 200
RSS contains slug = true
Sitemap contains slug = true
Database configured = true

多篇文章如何批量发布

批量发布时可以为每篇文章生成独立、单调递增的 migration:

0013_article_a.sql
0014_article_b.sql
0015_article_c.sql

这样更容易审查、回滚和定位故障。最终回读时不要只抽查第一篇;数量不多时逐篇验证,数量较多时至少核对总数并对代表性文章做正文断言。

安全边界也属于发布质量

文章发布前要清理:

  • 本机绝对路径和用户名;
  • .env、API Key、访问令牌和临时仓库凭据;
  • 未脱敏日志、Cookie、会话数据;
  • 只在本地成立的内部地址;
  • 不应该公开的第三方受保护文件内容。

Git 提交公开后很难真正抹掉历史,所以脱敏应该发生在提交之前,而不是部署之后。

结论

Markdown 是内容源,D1 是运行时记录,RSS 和 sitemap 是外部发现入口。真正的“文章已发布”意味着这四个表面在生产环境里指向同一份内容。

把检查写成固定流程后,博客发布就不再依赖“我打开首页好像看到了”,而是有一组可以重复执行、可以留证据、也能快速定位失败层级的验收标准。

zemeng5208

zemeng5208

@zemeng5208

全栈开发者 · 终身学习者

喜欢用代码解决问题,也喜欢把踩坑与收获写下来。关注前端工程化、TypeScript 与可读性。

2 粉丝 · 6 仓库

相关文章

评论