如果只是想搭一个能写文章的博客,你大概率不需要Hugo那套复杂的配置体系。Hugo确实强大,主题多、文档全,但对一个只想“安静写字”的人来说,它更像是一台高性能跑车——能跑赛道,但也得花时间熟悉仪表盘。我最近一直在用Caveman这个用Go编写的极简静态网站生成器,它在技术圈不算最火爆,但设计理念非常对我胃口:零配置、零依赖、构建快,整个工具链压缩到只有两条命令。这篇文章会从Caveman的核心设计讲起,带你完成安装、项目初始化、模板定制、内容写作、构建部署,把从零到上线的完整链路走一遍。适合两类人:一是被Hugo/Jekyll折腾烦了、想换个省心方案的内容创作者,二是对静态站点生成器原理有兴趣、想找一个干净利落的工具来研究的好奇者。
1. Caveman的核心设计理念:为什么说它是一股清流
1.1 静态网站生成器要解决的真正痛点
静态网站生成器的核心价值,是彻底绕开动态网站每次请求都要查询数据库、渲染模板、校验会话的链路。当你的内容只是几篇文章时,这些开销完全是浪费。SSG的思路是把所有内容在构建阶段一次性处理好,输出纯静态文件,部署到任意服务器或对象存储上,用户访问时服务器只负责把文件内容原样发出去。
我用一个类比解释这个过程:Markdown文章像食材,HTML模板像模具,构建命令像一个自动化厨师,它把食材清洗、切好、放进模具,最后烤出成品HTML饼干。对比传统动态站,这个烹饪过程发生在发布前,而不是每次用户访问时。所以SSG站点的优势是快、安全、省资源,不需要时刻运行数据库和中间件。
Caveman在这个赛道里属于“极简派”。它不像某些SSG那样提供几十个概念和无数配置项,而是只保留最核心的内容解析、模板渲染、静态资源拷贝三个能力。这个取舍看起来简单,实际上已经覆盖了个人博客99%的需求。你不需要为了一个博客页去理解主题系统、短代码、输出格式、数据文件、分类法这些概念,这些Caveman都不强加给你,而这也正是它能打动人的地方。
1.2 零配置背后的“约定优于配置”
很多SSG文档第一页就甩出一堆配置项:title、baseURL、theme、params、menu、taxonomies……写个博客而已,搞得像要发布一个商业系统。Caveman最吸引我的地方是它把“约定优于配置”做到了极致:你不写配置文件,它也能按一套合理的默认规则工作。
它的约定主要落在两个地方。第一是目录结构,content放Markdown、layouts放模板、static放静态资源,这套固定命名让Caveman在构建时不需要询问“内容在哪”,直接按默认路径扫描。第二是front matter,每篇文章头部的元信息字段(标题、日期、标签、布局)决定了它在页面中的表现方式,而不是通过外部配置去关联。
我刚开始用的时候也不理解为什么不提供更多选项。后来想明白了:每暴露一个配置项,就多了一份“我要不要调”的决策成本。Caveman的设计者故意把选择收敛,让新手一上来就能跑通全流程。等你真的需要自定义时,可以直接改模板,或者增加字段,不会被框架的配置结构限制住。这种设计哲学在编程领域有两个名字:一个叫convention over configuration,另一个叫defaults that just work。
1.3 Caveman与其他主流SSG的对比
我试着把Caveman和市面上几个主流SSG放在一起对比,这样你能快速判断它适不适合自己。
| 项目 | 语言 | 配置复杂度 | 适用场景 |
|---|---|---|---|
| Caveman | Go | 极低 | 个人博客、小文档站、作品集 |
| Hugo | Go | 中等偏高 | 大型文档、多语言站点、复杂结构 |
| Jekyll | Ruby | 中等 | 技术博客,依赖Ruby环境 |
| Eleventy | JavaScript | 中低 | Node生态用户、熟悉JS模板 |
从语言生态看,Hugo和Caveman都是Go,单二进制部署是共同优点。区别在于Hugo把大量功能内置了,而Caveman选择“够用即可”。Jekyll在GitHub Pages上被默认支持,但那也意味着本地要有Ruby环境,如果你不想为这个专门装Ruby,Go二进制的Caveman显然更轻。Eleventy适合本来就混在Node生态的人,但它的模板系统选择极多,学习路径反而更散。
我的判断标准很简单:如果站点内容以文章为主,层级结构简单,不需要复杂的分类体系和多语言,Caveman就是首选。如果需要在多个维度组织大量内容、做严格的输出格式定制,那就老实选Hugo。Caveman也不适合想做SPA动态交互页面的情况,它的长处是内容分发,不是复杂客户端逻辑。
2. 环境准备与安装:三种方式任选
2.1 方式一:通过Go工具链安装
如果你机器上已经有Go编译器,安装Caveman是最简单的。执行:
go install github.com/cavemanforge/caveman@latest安装到$GOPATH/bin或~/go/bin目录下。如果你执行caveman提示命令不存在,八成是PATH里没有包含这个目录。把下面这行加进~/.bashrc或~/.zshrc:
export PATH=$PATH:~/go/bin然后再开一个新终端窗口验证。用Go安装的好处是自动拉取源码并编译,后续升级时只需要重新执行同样的命令,版本管理非常省事。因为是Go生态,安装过程不会污染系统目录,也不会像RubyGems或npm那样装一堆依赖包,干净得很。
2.2 方式二:直接下载预编译二进制
如果你不想安装Go编译环境,去Caveman项目的GitHub Releases页面,按平台下载即可。Linux和macOS下载tar.gz压缩包,Windows下载zip,解压后得到一个可执行文件。把它放到系统PATH下的某个目录(比如定位到/usr/local/bin),就可以直接用了。
这种方式最适合部署到服务器。服务器上通常不需要Go工具链,一个二进制文件,哪怕是ARM架构的云主机,只要下载对应架构的release版本就能运行。这也是Go项目的好处:跨平台零依赖,很难出现“明明在本地能跑,上服务器就报错”的情况。我出过一次小问题:服务器是ARM架构,一开始我下载了amd64版本,执行时提示无法运行,换下载arm64版本之后立刻正常。所以下载前先确认一下系统架构。
2.3 方式三:从源码编译
如果你喜欢从源码编译,在GitHub上clone仓库,然后在项目根目录执行:
go build -o caveman .这种方式用到的情况不多,我在有特殊调试需求时才会这么干。普通使用用前两种方式就够了。从源码编译的好处是你能看到全部实现,想改点默认行为直接改源码重新编译,适合对Caveman工作机制好奇的人。我见过有人为了调整URL生成规则,在源码里找了几分钟就改好了,这正好说明Caveman的代码量很小,才给了你这种自由度。
2.4 验证安装与版本管理
无论用哪种方式装好,先验证:
caveman version如果输出版本号,说明安装成功。我建议确认当前版本不是老古董,因为Caveman的模板语法和部分命令在早期版本里不太一样。版本管理方面,如果你用Go安装,@latest会拉取最新稳定版;用预编译二进制时留意一下发布页面,选择带release标签的版本,不要下载处于开发中的快照。我在0.3版本踩过一个小坑:旧版本构建时偶尔会输出空目录,升级到较新版本后才恢复正常,所以我后来都尽量保持工具版本更新。
3. 项目初始化与目录结构:先跑起来再谈优化
3.1 初始化项目:一条命令的事
安装完Caveman,第一步自然是新建项目。我用过的方式是:
caveman init my-blog这条命令会在当前目录下创建一个名为my-blog的文件夹,并生成一套基础模板和一个示例文章。有了示例文章,你就能立刻跑通构建和预览,不需要一上来面对空白页面,这对建立信心很有帮助。如果你不想新建目录,也可以直接在已有目录里执行初始化命令,它会默认在当前位置生成结构。不过我建议还是新建一个干净目录,避免和已有文件混在一起。
3.2 认识目录结构:content、layouts、static
初始化完成后,目录大概是这样的:
my-blog/ ├── content/ │ ├── index.md │ └── posts/ │ └── hello-world.md ├── layouts/ │ ├── base.tmpl │ ├── index.tmpl │ └── post.tmpl ├── static/ │ └── css/ │ └── style.css └── caveman.toml我逐个解释。content目录放Markdown文章,其中index.md是首页内容,posts目录放文章。layouts目录放HTML模板,base.tmpl定义全站骨架,index.tmpl负责首页,post.tmpl负责单篇文章页。static目录放CSS、JavaScript、图片等资源,构建时会原封不动拷到输出目录。caveman.toml是唯一的配置文件,站点名称、描述等基础信息写在这里。
对比Hugo那种动辄十几二十个目录、几十个模板文件的布局,Caveman这套结构肉眼可见地精简。它的逻辑非常直接:内容归内容,模板归模板,资源归资源。我后来在管理多个小项目文档站时,一直沿用这套约定,团队新人接手也能在五分钟内找到该改的地方。如果你以后想加一个关于页面,只需要在content目录下新建about.md;想加一个标签页,多半只需要动layouts目录,这就是结构清晰带来的好处。
3.3 配置文件caveman.toml的常用字段
虽然Caveman允许你完全不配,但我还是会写一点基础信息。典型的caveman.toml内容:
title = "我的博客" description = "记录关于Go和静态站点的事" baseURL = "https://example.com" language = "zh-CN"title会出现在浏览器标签和页脚,description用于SEO描述,baseURL关系到最终生成页面上绝对链接的拼装,language会体现在HTML的lang属性上。我不建议在一开始就配置大量无关参数,保持最小配置即可。等你慢慢发现某个功能确实需要配置项时再加,这才符合极简工具的逻辑。比如后来我为了让RSS输出更完整,才往配置里加了author和copyright字段;在此之前它们根本不需要存在。
4. 模板系统详解:布局、连接与变量
4.1 模板变量从哪里来
Caveman的模板语法基于Go标准库的html/template,写法上其实是输出变量、条件判断和循环。模板里的数据来源有三个地方:front matter、全局配置、运行时的上下文结构。
比如单篇文章模板里,可以用{{ .Title }}输出标题,这个Title变量来自对应Markdown文件的front matter。如果想在全站所有页面都显示站点名,就用全局配置里的title,在大多数模板上下文中可以直接访问。如果你熟悉Go的模板包,几乎不需要额外学习。不熟悉也没关系,看到写法就能猜出大概:双大括号包起来的就是模板表达式,.开头表示取当前上下文的字段。
4.2 base模板与继承机制
这是Caveman模板系统里最值得理解的部分。base.tmpl定义全站公共骨架,比如:
<!DOCTYPE html> <html lang="{{ .Lang }}"> <head> <meta charset="utf-8"> <title>{{ .Title }} - {{ .SiteTitle }}</title> <link rel="stylesheet" href="/css/style.css"> </head> <body> <header>Caveman Blog</header> {{ block "content" . }}{{ end }} <footer>Copyright 2025</footer> </body> </html>block指令在base里挖了一个坑。首页模板index.tmpl通过{{ define "content" }}来填这个坑:
{{ define "content" }} <h1>最新文章</h1> {{ range .Posts }} <article> <h2><a href="{{ .URL }}">{{ .Title }}</a></h2> <p>{{ .Summary }}</p> </article> {{ end }} {{ end }}模板继承的价值在于:公共部分只维护一份,改导航栏、加统计代码、换字体,只要改base即可全站同步。这个机制从我第一天开始用就一直受益,尤其是后来给博客加了搜索框和回到顶部按钮,只动了base,几十个页面一起生效。如果每个页面都是独立完整HTML,你就得在几十个文件里重复做同样的事情,维护成本会瞬间失控。
4.3 partials局部模板:消灭重复代码
页面级模板之间的重复模块,可以抽成partials片段,放在layouts/partials/目录下,然后在页面里引用。假设建一个card.tmpl,里面写文章卡片:
<article class="card"> {{ if .Thumbnail }}<img src="{{ .Thumbnail }}" alt="封面">{{ end }} <h3><a href="{{ .URL }}">{{ .Title }}</a></h3> <p>{{ .Summary }}</p> </article>首页和归档页面想复用这段,只需要用{{ partial "card" . }}引入。这个功能对维护的影响非常大。我早期写过一段混乱模板,首页和归档页各复制了一份卡片样式,后来改卡片圆角和阴影,改了两处都没完全同步。抽成partial之后,改一处全局生效,再没有这种烦恼。命名上我也建议遵循一个简单的规则:card、sidebar、header、footer这些一看就懂的名字,不要用缩写或者无意义编号。
4.4 列表页的实现:range循环
博客的首页或者归档页本质上是一个“文章列表”。在模板里用range循环遍历文章:
{{ range .Posts }} <li><a href="{{ .URL }}">{{ .Title }}</a> - {{ .Date.Format "2006-01-02" }}</li> {{ end }}这里值得一提的是.Posts是通过站点数据注入的,Caveman在构建时会把内容目录里的文章按规则聚合起来传给模板。你在模板里不需要关心文章从哪里来,只需要用range逐条渲染。这和使用普通编程语言做循环的思维一致,不需要额外的框架知识。值得注意的是Go模板里的日期格式模板字符串是固定的2006-01-02,这是Go诞生的纪念日时间点,不是随意写的,第一次接触时可能会觉得奇怪,习惯了就好。
5. 内容写作实战:从零到一篇结构完整的文章
5.1 一篇文章的完整生命周期
用Caveman写文章,完整流程大概是:在content/posts目录新建一个Markdown文件,写好front matter和正文,保存后在本地预览里检查效果,最后执行构建,把输出部署上去。
这个流程我在使用中尤其喜欢一点:整个过程没有数据库、没有后台编辑器、没有版本冲突。文件系统就是内容仓库,Markdown是唯一内容格式。换电脑写作也简单,只要把仓库clone下来,上面说到的同一套流程继续跑,不会有任何环境差异。它把“写文章”这个动作简化成了“编辑一个文本文件”。对我这种喜欢用不同设备写作的人来说,这个特性非常实用。
5.2 Front Matter设计建议
我推荐的最小字段集如下:
--- title: "用Caveman搭建极简博客" date: 2025-01-15 tags: ["go", "ssg"] layout: post ---title和date不用多说。tags用于内容分类和组织,你可以在首页模板里遍历显示,也可以基于它做标签页。layout指定这篇文章使用哪个模板,默认值是post,所以大多数文章可以不写这个字段,等你有页面级特殊模板需求时再显式声明。
除了这些,我还有一个习惯:给每篇文章写一个summary。这可以让首页列表更友好,不用截断正文,也能很好地保持列表页的整齐。summary属于可选字段,但强烈建议你有就填。另外一个容易被忽略的经验:title字段不要写太长,控制在四五十个字符以内,这样首页列表、浏览器标签、社交媒体分享卡片都不会被截得很难看。
5.3 分类、标签与归档的一种实现思路
Caveman本身对分类和标签的支持十分朴素,它不会自动生成/tag/之类的归档页。这听起来像缺功能,但通过模板完全可以实现。思路是:在内容数据里,每篇文章的tags字段会被聚合进一个全站文章列表。你可以写一个tag归档模板,遍历所有文章,按tags字段做分组,输出同一个标签下的所有文章链接;然后把这个归档模板挂在某个固定路径的页面下。
具体过程对模板要求不算高,但你需要理解Caveman在构建时注入的数据结构,就是前面说过的.Posts、.URL这些字段。如果你只是想要一个简单的所有文章页面,那就更简单:在首页模板里遍历全部文章,分年或者不分年地输出列表,再美化一下,完全够用。我个人把这个页面命名为archives,效果不比大型博客差。等文章量超过一百篇,归档页的价值就会显现出来,所以建议早点加上。
5.4 Markdown中的代码、图片与摘要
用Markdown写代码块、插入图片,这是基本操作。我提一个容易被忽略的点:Caveman生成的HTML页面,正文区域的内容默认不会做额外转义,所以你在Markdown里写的HTML标签也会保留。这算是一个兼顾灵活性的设计:如果你想在某篇文章里嵌入特别的表格或者组件,可以直接写原生HTML,模板不会拦你。
图片方面,我习惯把图片放在static/images目录,文章里用相对路径引用。前面也提过,如果站点部署在子目录,绝对路径容易出问题,你在写第一篇文章时就该养成相对路径的习惯。摘要方面,除了front matter里写summary,部分版本也支持在正文中设置摘要分界标记,具体看你用的版本文档。我自己的建议是坚持用front matter里的summary字段,这样摘要和正文分离,以后想换摘要措辞也不用动正文内容。
6. 构建与本地预览:开发调试闭环
6.1 build命令与输出目录
常规构建命令是:
caveman build它会扫描content、读取layouts、处理static,最后把结果写到输出目录。拿到输出目录后,你可以用任何静态服务器托管它。我每次构建完会先检查几个关键文件:首页HTML是否正常拼接、文章列表顺序是否对、静态CSS是否被拷贝。这种手工确认的习惯帮我处理过不少问题,推荐你也保留。特别是第一次部署前,这个检查能帮你提前发现路径和模板问题,不至于部署到线上才发现整站样式全丢了。
6.2 serve命令:本地开发服务器
写内容时,我更依赖预览功能:
caveman serve -p 8080启动后访问http://localhost:8080,可以看到站点全貌。Caveman的serve进程会监听文件变化并自动重建,浏览器刷新即可。这个特性让模板调试效率高了不少:改一行CSS,刷新页面看效果;改模板结构,候一下就重建。对写作者来说,这种即时反馈很重要。如果你同时开着多个项目,建议用-p参数指定不同端口,避免冲突。
6.3 性能实测与资源占用
我拿自己一个包含230篇文章的博客仓库做过测试,Markdown大约4万行。执行一次完整构建,耗时在1秒以内,输出目录大约生成几百个HTML文件。由于构建过程几乎是纯CPU和IO操作,内存占用很小,不像某些框架启动就要吃掉几百MB内存。
性能好的原因在于Caveman功能少:解析Markdown、渲染模板、拷贝文件,没有第三方主题引擎的中间层。对于个人博客这种量级,构建速度完全不会成为瓶颈。即使每天写一篇,一年积累也就三四百篇,仍然是秒级构建。如果你有一台树莓派或者低配云主机,跑Caveman构建也毫无压力,这一点在服务器资源有限时非常友好。
7. 部署上线的完整方案
7.1 GitHub Pages:最省心的零成本方案
GitHub Pages是我个人博客的首选。整体流程是:新建一个仓库,把Caveman项目和构建产物推上去,然后在仓库设置里开启Pages功能,选择对应的分支。你一旦开启,就能得到一个免费的HTTPS域名。如果你有自己的域名,也可以在Pages设置里绑定,GitHub会帮你配好证书。
为了把流程自动化,可以在仓库里配置GitHub Actions,在每次推送时自动执行安装、构建、推送到Pages分支。这套方案完全免费,维护成本极低。唯一需要注意的是GitHub Pages对国内访问有时不太稳定,但作为默认方案,它的性价比非常高。我用GitHub Pages跑了一个技术博客差不多两年,没花过一分钱服务器费用,稳定性也足够。
7.2 Netlify/Vercel:提交即发布
如果要更成熟的发布链路,Netlify和Vercel都很容易上手。以Netlify为例:把仓库连好后,在Build命令里填caveman build,在Publish directory里填输出目录,每次git push都会触发自动构建,并把预览地址直接发给你。
这套流程的价值在于“提交即发布”的心智模型。你不需要记得构建和上传,所有操作收敛在git push一个动作里。我推荐用Vercel,它对静态站点的构建速度和配置便捷度更好一些。如果你已经有云平台账号,也可以看已有的Caveman社区模板,通常会预配好环境。我自己的几个演示站点就挂在Vercel上,构建日志很清晰,出问题时排查也比较方便。
7.3 对象存储+CDN:更适合国内的方案
如果你的读者主要在国内,那么最适合的方式是把生成的静态文件上传到对象存储,再套一层CDN。流程不复杂:在对象存储服务里创建一个桶,把output目录同步上去,然后在CDN控制台添加域名,配置回源到对象存储。
我实际用下来的问题是缓存刷新:更新文章后,如果CDN缓存没有及时过期,旧内容会残留在边缘节点上。解决办法是在每次发布后调用CDN的刷新接口,强制清掉对应目录的缓存。对象存储+CDN的成本很低,按流量付费,个人博客每个月基本就几毛钱到几块钱。速度和服务质量比用境外托管明显更好。如果你有国内备案的域名,这个方案是长期运营的稳妥选择。
7.4 附:一个可参考的CI流程
如果你用GitHub Actions,核心流程可以这样设计:
name: Build and Deploy on: push: branches: [main] jobs: build: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: Setup Go uses: actions/setup-go@v5 with: go-version: '1.21' - name: Install Caveman run: go install github.com/cavemanforge/caveman@latest - name: Build run: caveman build - name: Deploy run: rsync -av --delete output/ server:/var/www/blog/这只是我最常用的一种形态,你可以按自己的服务器和平台调整。CI的关键价值是:每次改动都会走一遍和本地完全相同的构建流程,从源头上避免“本地能跑、线上不行”的问题。我在开始写博客早期就上了CI,虽然前期花了一点配置时间,后面省下的时间远多于投入。如果你用的是对象存储,也可以把Deploy那一步替换成对应的同步命令行工具。
8. 常见问题与排查技巧:我踩过的坑
8.1 模板修改不生效
开发模式下改了模板,刷新却没有变化。原因大概率不是Caveman坏了,而是文件监听失效或者进程缓存。先试试重启serve进程。如果你在Windows环境使用Vim等编辑器,保存文件时的临时文件机制也偶尔会干扰监听,在监听可靠度上不如直接在Linux或macOS下跑得稳。
生产环境出现模板不更新的问题,则优先排查CDN缓存,而不是怀疑构建结果。清理域名下的缓存目录后重新验证,十有八九马上恢复正常。这是我踩过一次坑之后的固定排查顺序:先看缓存,再看构建结果,最后才怀疑工具本身。多数情况下问题出在前两方面。
8.2 资源路径404
页面打开后CSS和图片全部加载不出来,几乎都是路径问题。绝对路径/css/style.css在站点部署到子目录时会失效,所以尽量在模板里写相对路径,或者在配置里正确设置基准路径。
排查时可以先打开浏览器控制台,看Network标签里具体请求了哪些URL。如果URL前缀多了一层目录,那就是路径问题没跑。统一改用相对路径,或者确认baseURL和部署目录一致,就能规避。我个人的习惯是模板里一律用相对路径,这样不管把站点推到GitHub Pages的某个仓库目录,还是放到自己服务器的子路径,都能保持正常。
8.3 中文乱码与URL编码
模板或文章中中文输出乱码,第一步检查文件编码是不是UTF-8,尤其要注意在Windows记事本保存时是否被转成了带BOM的格式。构建结果HTML里的meta标签也要确认charset是utf-8。如果中文出现在URL里,先检查是否有slug字段,没有就给文章加一个英文slug,让URL更干净可读。
这个坑看起来小,实际遇到的时候很让心态崩溃。我早期有一批文章是用老工具导出的,文件编码是GBK,构建出来后整页乱码,找了好久才意识到是源文件编码问题。后来我把所有源文件统一转成UTF-8,并且写人一个转换脚本,以后再没出现过乱码。
8.4 文章顺序不对
列表页文章排错顺序的原因,九成是front matter里的日期格式不一致。有的写2025-01-15,有的写2025/01/15,解析结果就会混乱。建议统一用ISO8601格式,比如2025-01-15T10:30:00+08:00。如果你不想在front matter里写时区,最简单的2025-01-15也可以稳定解析。排查时直接在content目录执行搜索,把不同格式的date全部找出来统一。
另外,如果你修改过文章的front matter,但发现列表顺序没变,可能是构建缓存。Caveman一般不会缓存文章顺序,但如果你用的是旧版本,清一下输出目录再重新build就能解决。
8.5 代码块无高亮
Caveman默认不集成代码高亮,代码块在生成后是纯文本。这倒不是缺陷,而是一个设计取舍:让模板和内容简洁,把高亮工作留给前端更灵活。我也建议你在前端引入highlight.js或PrismJS,在base模板中链接它们的CSS和JS脚本,然后初始化即可。
如果某些代码块没有被正确识别,多半是Markdown里代码块语言标识写错。比如代码块里写的是python,实际使用的时候误写成了pytho,高亮库就无能为力了。另一个小经验:高亮脚本的初始化最好放在所有DOM渲染完成后执行,不然动态加载的内容不会被高亮,这个问题在单页切换时尤其明显。
8.6 构建结果与预览不一致
本地预览正常,但build出来的文件却表现不同。一个典型原因是serve模式会自动调整部分配置或路径,而build使用严格模式。另一个常见原因是你在本地预览时浏览器启用了缓存。遇到这种问题时,先clean构建产物再重新build,或者打开浏览器无痕模式测试。大多数情况下,不是工具出了玄学问题,而是缓存或环境残留。
我会特别提醒一点:改动base模板里的全局结构后,别只看首页,要多点开一两篇文章页面看看。有时候首页正常,文章页因为某个变量为空就会出现布局错位,这种问题只有在多类型页面里检查才容易暴露。
9. 个人体会与后续扩展
把整套流程跑下来之后,我最深的一个感受是:工具的设计哲学会影响你写作时的状态。用Caveman写的每个页面都感觉很轻,因为我没有被配置清单、依赖版本、构建脚本这些杂事干扰,专注力始终在内容本身。这是我持续使用它的最大理由。
后续如果想扩展,我打算做两件事。一是给模板补充更多辅助函数,比如自动生成上一篇/下一篇链接、文章字数统计;二是研究一下给Caveman加一个简单的分页能力,让归档页在文章特别多时也能保持良好的浏览体验。这些扩展都不需要改变它的核心机制,仍然只是补齐模板和辅助数据。
如果你也在纠结静态博客选什么,给Caveman一个周末的时间,按这篇文章走一遍,应该能感受到“零配置”这三个字背后的用心。哪怕最后不用它,理解它的约定和取舍,也会让你在选择其他SSG时更清楚自己要什么。工具永远服务内容,别把顺序搞反了。