把发布脚本变成质量闸门:Docusaurus 站点在 build 前该挡住什么
以前我对博客发布脚本的要求很低,能把 build -> 上传 -> reload 跑通就算不错。等 blogV2 的文章越来越多、迁移批次越来越频繁以后,这条认知很快就被现实打掉了。因为对内容站来说,最贵的成本不是手工上传慢十秒,而是坏内容已经被发到线上以后,才发现链接错了、description 烂了、文章根本还是半成品。
所以我现在看发布脚本,先问的不是“自动化程度高不高”,而是“它有没有能力在上线前说不”。如果脚本只能搬运产物,那它只是个勤快的快递员;真正值得维护的脚本,应该先当质量闸门,再当部署工具。
build 能过,不等于这次内容值得发布
静态站特别容易让人产生一种误判:页面能生成,说明站点就健康。这个判断只对了一半。docusaurus build 能验证渲染层没挂,却不会替你判断这次内容是不是明显有问题。比如:
- 标题和 description 是不是写成了同一句空话
- 有些文章是不是还残留模板占位段
- 旧文迁移后有没有把地址和归档关系带乱
- 某篇文章净正文是不是根本没达到公开发布的程度
这些问题如果不在 build 前挡掉,等产物已经上线,再回头修就是两遍成本:先修内容,再补部署。
blogV2 现在这条链路,已经不是单步构建了
package.json 里现在最关键的一段,其实不是 build,而是这条生产构建链:
{
"scripts": {
"build-prod": "npm run clear && npm run migrate:blog && docusaurus build",
"deploy:prod": "./scripts/deploy-static.sh root@117.50.172.254 /var/www/blog"
}
}
这段脚本最有价值的地方,不是命令多,而是顺序对。先清缓存,避免旧产物混进来;再跑 migrate:blog,把历史内容、归档数据和开发 sitemap 重新整理;最后才让 Docusaurus 生成站点。部署脚本则被放到最后,只负责搬运已经通过检查的产物。
迁移和标准化,应该是 build 前的固定动作
scripts/migrate-blog-posts.js 不只是“把旧文导进来”那么简单。它会做几件特别适合放在 build 前的事:
- 统一 frontmatter 基础字段
- 生成
src/generated/legacyArchiveData.json - 生成开发环境下的
static/sitemap.xml - 在合适的情况下保留本地补写过的更优版本
这一步如果省掉,后面的 build 很可能面对的是一堆彼此不一致的内容输入。页面也许还能渲染,但最近文章、归档、链接和索引关系已经开始漂了。
薄内容、坏 metadata 和模板残留,最好提前拦截
我现在特别赞同把内容质量测试放到构建前,原因不是追求“严格”,而是它们很适合让机器稳定执行。tests/thin-content-remediation.test.js 会把净正文低于 500 字的内容拦下来,tests/blog-content-quality.test.js 会检查模板短语、description 重复标题、导出噪音和风险内容。这几类问题都很典型:人工能看出来,但每次靠人工翻全站去找,成本极高。
对内容站来说,这些检查有一个很实际的好处:它们把“作者以为已经写完”和“读者真的拿到了一篇像样的文章”之间的差距提前暴露出来。
发布前最小检查清单,我宁愿保守一点
如果今天只保留一份最小清单,我会把它写得很朴素:
- frontmatter 关键字段存在,并且格式可信。
- 标题、description、slug 没有明显退化成占位值。
- 正文不是薄内容,不是几句提纲冒充一篇文章。
- 历史迁移、归档数据和最近文章索引同步更新。
- 最终站点 build 能完整通过。
这个清单看起来不复杂,但足够挡住绝大多数“本来应该在本地解决”的返工。
发布脚本最重要的品质,不是快,而是敢停下来
我越来越不喜欢那种只负责一路往前跑的脚本:
build
rsync
reload
它当然也能工作,但对一个长期维护的内容站来说,太像只管把货送出去,不管箱子里装了什么。真正成熟的发布脚本,应该先判断“这次允不允许发”,再去做部署动作。否则脚本越顺滑,坏内容越容易被高效率地送上线。
我现在更看重的,是脚本替人守住发布边界
对 blogV2 这种长期内容站来说,发布脚本真正值钱的地方,不是把上传时间再省十秒,而是把“这次 description 还有导出噪音”“那篇旧文其实还没补完”“某批迁移把归档数据打乱了”这类问题,尽量挡在 build 之前。
构建、迁移、质量测试和部署这几步连起来以后,发布才不像一次仓促上传,而更像一条能长期重复执行的生产线。对我来说,这才是脚本化发布真正的小改进:不是命令更花哨,而是边界更清楚,坏内容更难混过去。
