跳到正文
WC.

把构建时校验当产品

•1 分钟阅读•架构•
•
#validation#static-sites#zod#dx

「在生产环境出错」是默认状态。坏链照样上线,主题描述里有个 typo 没人发现,frontmatter 少必填字段 build 照样跑——直到某页渲染错或 feed 崩了。错误在用户打开页面或你几周后才发现时出现,那时问题已经上线、被缓存,更难回溯。

改成在构建时失败。把校验当成内容流水线的一等公民。有问题就不让 build 成功。不部署、不「下个 PR 再修」。作者拿到明确报错和文件路径,改完再 push,流水线保持可信。

构建时校验关卡图,展示内容检查如何阻止无效部署。

从「希望没坏」变成「流水线拒绝发布有问题的东西」——这就是我所说的「构建时校验作为产品」。产品不是内容本身,产品是对「发布出去的东西是合法的」的信心。一小套脚本就能做到。

校验什么

链接、主题描述、元数据和 frontmatter。校验站内链接,保证没有文章或项目页指向不存在的 slug。校验主题描述,保证 frontmatter 里引用的每个 theme 都在主题列表或 UI 配置里存在。校验元数据,保证 Open Graph、标题、描述存在且长度合适。用 schema 校验 frontmatter——Zod 很合适——保证必填字段存在、类型正确、tags 或 theme 在允许集合里。

每个校验都是一个脚本:validate-links、validate-theme-descriptors、validate-metadata、validate-frontmatter。在 CI 或 pre-build 里跑。有一个失败 build 就失败。不静默漂移。

为清晰报错设计

最差的校验器只会说「校验失败」然后没了。作者需要知道什么坏了、在哪。输出文件路径、字段或行号、以及违反的规则。「content/writing/my-post.mdx 缺少必填字段 theme」比「Invalid frontmatter」有用得多。用 Zod 的话,自定义错误信息或用 .refine() 写清文件和期望。Stack trace 是给开发看的;内容作者需要一句话就能知道该改什么。

输出要易扫:一行一条问题,或简短摘要加列表。在 CI 日志里,作者应在十秒内看到失败并知道该打开哪个文件。

为什么值得做

校验一旦到位,作者可以放心改。重构 slug、重命名 theme、改 frontmatter 结构——流水线强制执行约定,拒绝发布错误。新贡献者立刻得到反馈:修掉报错,build 就绿。不需要口口相传;build 就是检查。

我把构建时校验当产品,是因为它改变了默认。默认不再是「发出去再祈祷」,而是「系统在合法之前不会发布」。那就是产品——一个你可以信任的内容流水线,以及告诉你该修哪里的报错。

继续阅读

无服务端的跟读音频

网站上的跟读音频通常意味着有一台服务器:用户点播放,服务端跑 TTS、推流,或者至少从数据库里查一条录音。我想在这个站上也有音频——播放按钮和可选的按词高亮——但不加任何运行时。站点保持静态:每页预渲染,CDN 只负责发文件。没有函数调用,生产环境也没有 TTS 用的 API key。…

•1 分钟阅读•架构
staticaudionextjs
在「万物动态」时代做静态优先

越来越多人倾向于在服务端动态渲染一切。Edge 来了之后,说法是动态渲染几乎免费:在 edge 跑个函数、毫秒级返回 HTML,用户无感。那还折腾静态生成干什么? 但物理规律还在。再快的 edge function 也快不过从 CDN…

•1 分钟阅读•架构
nextjsstaticperformance
把 GitHub 当后端

你可以跑一个带评论和动态的静态站,而不跑数据库也不跑 API。做法就是把 GitHub 当成你从不用运维的后端。 身份、存储、动态通常意味着鉴权、数据库和某种实时更新。对个人站或小项目来说,零件太多了。 我希望读者能评论,也希望展示近期工作——又不想再起一个服务或为评论 SaaS…

•1 分钟阅读•基础设施
githubgiscusstatic-sites
用 Resend 和 Cloudflare 从静态站发 newsletter

静态站不会在有人打开页面时跑代码,这正是目的。但 newsletter 需要动态:接收订阅、发确认邮件、处理点击、把联系人加进列表、发欢迎信。那怎么既保持站点静态,又完整掌控整个流程? 我的做法是:用 Resend 发信,用 Cloudflare Pages Functions 提供那一小块 API。HTML…

•1 分钟阅读•基础设施
newsletterresendcloudflare