#先说结论
不是说框架不好。Hexo 和 Hugo 我都用过,体验都很好。
但这次做站的时候,我发现我的需求其实只有一句话:
把
content/posts/*.md变成dist/下的一堆 HTML,顺便生成索引页、归档页和 RSS。
这件事,现成框架给了我一大坨我不需要的东西:主题系统、插件机制、标签分类的七种变体、几十个依赖。而我实际用到的 Markdown 语法,不超过十种。
#权衡
| 现成框架 | 自建脚本 | |
|---|---|---|
| 初始上手 | 装依赖、选主题、改配置 | 打开 build.js 改配置 |
| 依赖数量 | 50 ~ 300 个包 | 0 个 |
| 攻击面 | 每次 npm audit 都有东西 |
不存在 |
| 产物大小 | 主题带一堆用不上的 CSS/JS | 完全可控,首页 12KB |
| 定制自由度 | 受主题结构限制 | 想怎么改怎么改 |
| 十年后还能跑吗 | 看依赖树 | 一个 Node 文件,能跑 |
最后一条是我最在意的。一个纯静态博客的生命周期可能有十年,而 node_modules 里的某个包在第三年就会因为 Node 版本升级而跑不起来。
#实际写了多少代码
lib/markdown.js—— 约 200 行,Markdown → HTMLlib/templates.js—— 约 280 行,页面拼装build.js—— 约 200 行,文件遍历 + 索引 + RSS/sitemapassets/style.css—— 约 600 行,双主题样式
加起来 1200 行出头,全是我自己写的,没有一行第三方代码。
对比一下:用 Hexo 建站,光 node_modules 就有 180MB,构建产物还带着一个 400KB 的 jQuery。
#Markdown 解析器要写多少
这是我最初觉得最麻烦的部分,写完发现比想象的简单。核心就是一个行扫描器:
while (i < lines.length) {
const line = lines[i];
if (/^```/.test(line)) { /* 代码块,吃到下一个 ``` 为止 */ }
else if (/^\|/.test(line) && isTableDivider(lines[i + 1])) { /* 表格 */ }
else if (/^(#{1,6})\s+/.test(line)) { /* 标题,顺手收集 TOC */ }
else if (/^>\s?/.test(line)) { /* 引用,递归调用自己 */ }
else if (/^[-*+]\s+/.test(line)) { /* 无序列表 */ }
else if (/^\d+\.\s+/.test(line)) { /* 有序列表 */ }
else if (!line.trim()) { /* 空行,收尾段落 */ }
else { /* 普通文本,进缓冲区 */ }
i++;
}
行内规则(粗体、斜体、链接、图片、行内码)用几个正则就够了。关键是先把行内代码抽出来占位,处理完再放回去 —— 否则代码里的 * 会被当成斜体标记。
const codes = [];
out = out.replace(/`([^`]+)`/g, (_, c) => {
codes.push(c);
return `\u0000CODE${codes.length - 1}\u0000`;
});
// ...处理其他规则...
out = out.replace(/\u0000CODE(\d+)\u0000/g, (_, i) => `<code>${codes[+i]}</code>`);
这个技巧在很多 Markdown 实现里都能用。
#顺手做的一些事
写的时候顺手加了些小功能,都是"有需求时才加"的:
- 目录(TOC) —— 解析标题时顺手收集,渲染成侧边悬浮目录
- 深浅色双主题 —— 一个
data-theme属性 +localStorage,十几行 JS 搞定 - 阅读时长 —— 中文按 400 字/分钟,英文按 200 词/分钟算
- RSS / sitemap / robots —— 都是纯文本模板,几十行
- 标签页 / 分类页 —— 复用文章卡片组件
#什么时候该用框架
如果你:
- 不想碰构建流程
- 需要评论、搜索、订阅等动态功能
- 团队里有人不写代码
那用框架,别造轮子。Hexo + NexT 主题,五分钟就能上线。
但如果像我一样,需求明确到"就是 Markdown 转 HTML",而且你享受那种「整个站只有我知道它怎么工作」的踏实感 —— 那自己写一个真的挺爽。
#一个隐藏福利
自己写的好处是:站点永远不会"炸"。
没有依赖升级导致的构建失败,没有主题版本和 Node 版本不兼容,没有某天早上发现站打不开了还要去翻 issue。
一个纯静态 HTML 的目录,扔在任何能跑 Nginx 的地方都能跑。这才是"网站"最该有的样子。