建站3,767 字约 6 分钟

从 MkDocs 到 Astro

本站之前一直使用 MkDocs 框架和 Material for MkDocs 主题搭建。

说实话,这套组合的体验并不差。Material for MkDocs 提供了丰富的功能,包括导航、搜索、代码高亮、博客、Markdown 扩展等。几乎不需要编写什么前端代码,就能搭建出一个美观且功能完善的网站。

但是,MkDocs 本质上是一个面向技术文档的静态网站生成器,而我想要的是一个更加自由的个人博客。

随着时间的推移,这套方案也渐渐暴露出了一些问题。

为什么离开 MkDocs

项目的维护状况

首先是项目本身的维护问题。

MkDocs 1.x 已经很长时间没有正式更新。虽然 MkDocs 2.0 已进入预发布阶段,但由于架构上的调整,它并不能直接兼容现有的 Material for MkDocs。

而 Material for MkDocs 自 2025 年 11 月发布 9.7.0 版本后,也正式进入了维护模式,不再开发新功能,仅继续提供关键错误修复和安全更新,并计划于 2027 年 5 月 5 日结束上游维护。

后来,我又看到了 MkDocs 2.0 的讨论,以及 Material for MkDocs 团队对此发表的文章。

说实话,这让我对 MkDocs 的未来更加担忧。

MkDocs 2.0 选择彻底重写现有架构,并计划移除原有的插件系统。虽然这样能够降低框架本身的复杂度,但也意味着大量依赖插件和主题扩展的功能无法直接延续。

在讨论区中,有贡献者认为,正是 Material for MkDocs、PyMdown Extensions 以及不断发展的插件生态,才让 MkDocs 从一个基础的文档生成工具成长为功能完善的平台。如今新版本却选择放弃其中的重要部分,多少有些令人惋惜。

我并不反对重构,也能够理解维护者希望摆脱历史技术债的想法。但我更希望看到的是对现有扩展机制的改进,而不是直接将其移除。

再加上新版本的开发过程和社区贡献政策引发的争议,我对这个项目的长期发展方向也失去了一些信心。

尤其是对于我这样希望自由扩展功能、尝试不同 UI 设计的开发者来说,MkDocs 2.0 的发展方向显然与我的需求并不一致。

当然,这不意味着已经搭建的网站会突然无法使用。但对于一个准备长期维护的个人博客来说,我还是希望能使用一个持续发展、具备较好扩展前景的框架。

不太理想的 RSS 体验

这是我之前使用 MkDocs 时比较头疼的问题之一。

我希望博客能够提供 RSS 订阅,让读者直接在自己习惯的阅读器中查看新文章,最好还能阅读完整正文,而不必每次都跳转到网站。

MkDocs 本身没有内置 RSS,需要借助 mkdocs-rss-plugin 实现。

但之前配置时,我遇到了两个问题:

  • 非文章页面被收录。 RSS 阅读器不仅能看到文章,还会把网站的顶层页面也作为订阅条目收进去。
  • 只能阅读文章节选。 在 RSS 阅读器中打开文章时,只能看到一小段内容,想阅读完整文章还需要跳转到网站。

后来查阅文档才发现,插件默认会匹配所有页面,而文章内容也默认以摘要的形式输出。这些行为可以通过 match_path 和 abstract_chars_count 等参数调整。

问题并不是插件完全不支持这些功能,而是实际效果与我预期的博客订阅体验有些差距,还需要额外研究和调试配置。

考虑到这只是个个人博客,我也懒得继续折腾,索性就没有再配置 RSS。

文章摘要与正文耦合

还有一个让我不太满意的地方,就是 Material for MkDocs 博客插件生成文章摘要的方式。

按照官方提供的用法,需要在 Markdown 正文中插入 <!-- more --> 分隔符,插件会提取分隔符之前的内容作为文章概述。

这个功能本身没有什么问题,但它意味着:

我为了文章列表编写的概述,同时也会成为文章正文的一部分。

而我更希望文章概述和正文是两个独立的部分。

例如,一篇文章的摘要可能只是为了让读者快速了解它的主要内容,不一定适合作为文章开头。

如果使用独立的元数据字段存储摘要,就可以让文章列表、RSS 和 SEO 描述复用这段内容,同时不影响文章正文的组织。

这并不是什么严重的问题,但对我来说,独立管理摘要的方式更符合自己的写作习惯。

UI 定制的局限性

相比前面的问题,这才是促使我迁移的主要原因。

Material for MkDocs 的默认设计基于 Material Design,整体视觉风格偏向 Material 2。

它的设计确实不错,配色、字体、导航、布局等也都支持自定义,但整套主题的组件结构和设计思路依然是围绕文档网站建立的。

如果只是修改颜色、字体或者调整部分布局,这些功能已经足够。

但我并不希望自己的博客始终局限于 Material 2。

我想尝试其他的设计语言,例如 Material Design 3、Fluent Design,以及一些更简洁、偏向现代 Web 应用的设计风格。

甚至有时候,我可能根本不想遵循某一套完整的设计规范,只是想按照自己的想法制作几个组件。

而在 Material for MkDocs 中,要实现这些效果,往往需要覆盖原有模板、大量修改 CSS,或者绕过主题本身的组件结构。

这样做当然可行,但随着定制内容越来越多,维护成本也会随之增加。

与其在现有主题上不断修改,不如直接选择一个更适合自行构建 UI 的框架。

其他问题

此外,还有一些使用过程中的小问题。

例如,部分 Markdown 格式在特定文本环境下无法按照预期解析,需要手动添加空格或者调整语法。

这不一定是 MkDocs 本身的错误,也可能与 Python-Markdown 的语法规则或启用的扩展有关,但多少还是影响了一些写作体验。

这些问题单独来看都不算严重,也有对应的解决办法。

只是当它们逐渐积累起来,我开始意识到:我花在适应现有框架和主题上的精力,已经越来越多了。

于是最近,我决定尝试将博客迁移到其他框架。

为什么还是静态网站

一开始,我就排除了 WordPress、Typecho 等需要服务器运行环境的博客系统。

原因很简单。

首先是维护成本。动态博客通常需要维护应用程序、数据库、运行环境以及服务器配置,还需要定期安装更新、修复安全漏洞和备份数据。

如果服务器到期被释放,或者发生配置错误,在没有可靠备份的情况下,恢复数据可能会非常麻烦。

其次是安全问题。

动态博客通常会引入更多需要维护的服务端组件,攻击面也相对更大。尤其是一些长期缺乏维护的插件或依赖,可能成为安全隐患。

当然,静态网站不代表绝对安全,只是对于以展示文章为主的博客而言,我实在没有必要引入那么多额外的复杂度。

最后还有一个很现实的原因:

我是学生,(我没有钱)。

虽然我有自己的服务器,但并不想为了一个博客专门分配计算和存储资源。

使用 GitHub Pages、Cloudflare Pages 等服务托管静态网站,通常在免费额度内就能满足我的需求。

而且文章可以保存在 Git 仓库中,进行版本管理和备份。即使托管平台出现问题,也可以重新构建并部署网站。

所以,我仍然希望使用静态网站生成器。

为什么是 Astro

静态网站生成器其实有很多选择。

例如 Hugo、Hexo、Jekyll、Eleventy,以及之前使用的 MkDocs。

其中 Hugo 拥有非常成熟的博客功能,构建速度快,而且原生支持 RSS。

Eleventy 则提供了很高的自由度,允许开发者使用多种模板语言来构建网站。

这些框架都有自己的优势,也完全能够满足普通博客的需求。

但对我来说,个人博客并不只是一个发布文章的地方。

它同时也是一个可以自由尝试前端技术、UI 设计和交互效果的项目。

我本身就对前端开发比较感兴趣,也愿意花时间去实现自己喜欢的界面。

相比寻找一套足够完善的博客主题,我更希望从底层开始决定网站的结构与设计。

因此,我最终选择了 Astro。

不再受限于某种设计语言

这是我选择 Astro 最重要的原因。

Astro 不会强制网站采用某一套 UI 组件库或设计语言。

页面的结构、布局、颜色、交互和组件,都可以由自己决定。

想尝试 Material Design 3,就使用它的设计规范;想尝试 Fluent Design,就按照 Fluent 的视觉语言实现;如果只是想做一个非常简洁的界面,也完全没有问题。

Astro 采用组件化的开发方式,可以将导航栏、文章卡片、页脚等界面元素拆分为独立组件,再根据需要进行组合和复用。

同时,它也支持 React、Vue、Svelte 等前端框架,可以按需引入交互组件。

这让我不再需要围绕某个现成主题的内部结构进行修改,而是能够直接用熟悉的前端技术实现自己的想法。

更灵活的内容组织

Astro 原生支持 Markdown,并提供了 Content Collections(内容集合)来管理文章和元数据。

例如,可以将文章的标题、发布日期、标签、描述等信息放在 Frontmatter 中。

这样,文章摘要就不必再依赖 <!-- more --> 分隔符。

我可以单独编写 description,让它用于文章列表、RSS 或搜索引擎描述,而正文则完全按照自己的想法组织。

此外,Astro 还支持 remark、rehype 等 Markdown 处理插件,并可以通过官方集成使用 MDX。

如果以后需要一些特殊的 Markdown 语法、文章组件或者排版效果,也有比较灵活的扩展方式。

RSS 终于可以按自己的想法实现

对于 RSS,Astro 提供了官方的 @astrojs/rss 包。

与之前主要依赖插件配置的方式不同,Astro 可以通过 JavaScript 获取文章集合,自行决定哪些内容应该进入订阅源。

例如,我可以只收录正式发布的博客文章,不包含首页、关于页面以及其他无关内容。

也可以根据文章的分类、标签和发布日期进行筛选与排序。

更重要的是,我可以分别控制文章摘要和全文内容。

如果希望读者在 RSS 阅读器中直接阅读完整文章,可以通过额外的内容渲染逻辑输出全文 HTML,而不是只能看到一段节选。

当然,全文 RSS 仍然需要处理图片路径、内部链接和特殊组件等问题,并不是安装一个包就能自动解决。

但至少,这些行为都可以由我自己控制。

现代前端的开发体验

Astro 基于 JavaScript / TypeScript 生态,并使用 Vite 作为构建工具。

对于已经接触过现代前端开发的人来说,这些工具都比较熟悉。

需要额外功能时,也可以直接利用 npm 生态中的库和工具,而不必完全依赖某个静态网站生成器专属的插件系统。

另外,Astro 默认采用静态 HTML 输出,普通 Astro 组件不会自动向浏览器发送客户端 JavaScript。

只有确实需要交互的部分,才需要额外加载相关脚本或者使用 Islands Architecture(群岛架构)。

对于主要用来阅读文章的博客而言,这种设计很合适。

当然,这不代表使用 Astro 就一定能获得优秀的性能。网站的最终表现,依然取决于具体的实现方式。

但在保留静态网站优势的同时,还能获得现代前端框架的开发体验,确实很有吸引力。

迁移的代价

当然,迁移到 Astro 并不意味着所有问题都会自动解决。

MkDocs 和 Material for MkDocs 原本提供的导航、搜索、文章列表、归档等功能,在 Astro 中可能需要自行开发,或者使用现有的集成方案。

原有文章也需要进行一定的调整,包括 Frontmatter 字段、Markdown 扩展语法、图片路径等。

此外,还需要考虑旧文章 URL 的兼容性,避免因为更换框架而导致原有链接失效。

从工作量来看,这未必比继续使用 MkDocs 更轻松。

但区别在于,以前我是在适应一个已经存在的主题,而现在我可以按照自己的需求来组织整个项目。

对我来说,这种自由度值得付出一定的迁移成本。

最后

写这篇文章,并不是想说 MkDocs 或 Material for MkDocs 不好。

事实上,它们依然是相当优秀的文档工具,尤其适合需要快速搭建技术文档站、又不想投入太多前端开发精力的场景。

只不过,随着自己的需求不断变化,原本适合的方案也不一定能够一直满足需求。

从 MkDocs 迁移到 Astro,与其说是一次技术升级,不如说是一次开发思路的转变。

以前,我希望找一个足够完善的主题,尽量减少自己需要编写的代码。

现在,我更希望能够亲手决定这个网站应该是什么样子。

毕竟,这是我的个人博客。

既然如此,为什么不让它更有一点自己的风格呢?


参考资料

评论

滚动到此处后加载评论。

在 GitHub 讨论区查看或留言