---
title: "Yonnia.com"
description: "这个网站本身。零依赖的静态生成器，一行 JavaScript 都不发给浏览器。"
canonical: https://yonnia.com/projects/yonnia-site
language: zh
status: active
year: 2026
stack: ["Node.js","HTML","CSS"]
repo: https://github.com/yonnia/yonnia.com
homepage: https://yonnia.com
---
# Yonnia.com

这个网站本身。零依赖的静态生成器，一行 JavaScript 都不发给浏览器。

你现在看的这个网站，以及生成它的东西。

## 为什么自己写

我原本准备用 Astro。真正让我改主意的不是「不想装依赖」这种洁癖，而是一个很具体的观察：这个网站的 SEO 上限完全由输出的 HTML 决定，跟用什么工具生成它没有关系。而一个静态博客需要的 HTML，其复杂度远低于一个构建工具链。

于是范围反过来定义了工具：如果我需要的只是「把 Markdown 变成正确的 HTML」，那 Node 的标准库已经够了。

## 实际的构成

- 一个 CommonMark 子集渲染器，够用于我实际会写的语法
- 一个只支持我实际会用的结构的 YAML front-matter 解析器，遇到不认识的写法直接报错而不是猜
- 一张路由表，所有 URL——页面、Markdown 镜像、feed、sitemap——都从它派生
- 一个 `head()` 函数，独占所有爬虫可见的标签
- 一组 schema.org 构造器，每个实体有稳定的 `@id`，全站只定义一次

## 约束

- **零 JavaScript 输出。** 目录、语言切换、深色模式全部是服务端渲染或纯 CSS。
- **构建时校验。** 缺 description、标题过长、日期在未来、正文里有第二个 H1——构建直接失败，而不是安静地发出去。
- **构建后审计。** 一个独立脚本检查每个页面的 canonical 冲突、hreflang 互指、内链是否真的存在、JSON-LD 能否解析、图片有没有 alt 和尺寸。

## 代价

最明显的一个：没有增量构建，没有 HMR。全站重建大约 100ms，所以这两个都还不需要。等到需要的时候，内容是普通 Markdown，迁到 Astro 是一天的事。

第二个：我要自己维护 Markdown 渲染器。已经因为几个边界情况改过三次。这个成本是真实的，只是目前还低于一个依赖树的维护成本。
