前言
「佩璃的小屋」最早是用 Zola 搭的。刚开始只有几篇笔记的时候用着还挺省心,但随着我往博客里加了项目展示、截图图库、动态时间线和深浅主题,旧模板改起来越来越吃力。
10 月 12 日整理旧仓库的时候,我发现站里的几篇文章连头部配置(Front Matter)的写法都不统一:有的把分类、标签直接写在顶层,有的又包在 taxonomies 和 extra 里。如果模板少判断了一种写法,Markdown 看着好好的,生成的页面上却缺了封面或者分类。
与其继续在旧模板上打补丁,我干脆花时间把整个博客本地迁移到了 Astro,顺便把内容目录、字段规则和构建检查彻底理顺了一遍。
重要
迁移目标
- 坚持纯静态生成:不引后端数据库、不搞在线 CMS,也不为了几个按钮引入 React/Vue,关掉 JS 也能正常读文章看图。
- 统一内容结构:所有文章、项目和动态都用同一套扁平的顶层 YAML 字段,写错了在构建时直接报错提醒。
- 补齐全文搜索与自动检查:用 Pagefind 替换原来只搜摘要的旧搜索,并给链接、图片和草稿隔离加上自动化测试。
重构内容目录与字段规范
迁移当天,站里一共有 4 篇文章、5 个公开项目和 1 条草稿随记。我先把它们全部改成了按 ID 分目录存放的结构:
content/
├── articles/
│ └── wireguard-homelab/
│ ├── index.md
│ └── images/
├── projects/
│ └── my-blog/
│ └── index.md
└── activities/
└── first-note/
└── index.md这样改有两个很实在的好处:
- 网址和标题解耦:文件夹名字(比如
wireguard-homelab)直接决定文章 URL,以后想改文章标题随时都能改,不怕链接失效。 - 图片跟着文章走:每篇文章的配图直接放在自己的
images/目录下,用./images/xxx.png引用,再也不用像以前那样去全局static/images/目录里翻来翻去了。
文章开头的 YAML 配置也全部拍平,不再套 extra 或 taxonomies:
---
title: 使用 WireGuard 远程访问家庭内网
published: "2026-05-24"
draft: false
category: HomeLab运维
tags: [Linux, WireGuard, VPN]
cover:
src: ./images/wireguard.jpg
alt: WireGuard 软件图标
---依托 Astro 的 Content Collections 和自定义的检查脚本,现在只要字段名拼错、日期没加引号或者引用的本地图片不存在,运行检查命令时就会直接报错。迁移那天就靠这个抓出了旧 Neovim 文章里的一张失效封面引用。
统一内容发布与过滤规则
以前最怕出现一种尴尬情况:某篇草稿虽然没在首页列表里显示,但因为搜索索引或者 RSS 订阅源忘了加过滤,结果从侧门漏了出去。
这次迁移我把“判断一篇内容能不能公开”的逻辑统一收拢到了 src/lib/ 底下:
Markdown / YAML 源文件
↓ 字段与图片资源检查
统一的发布与排序规则(src/lib)
├── 页面列表与文章正文
├── Pagefind 搜索索引数据
├── RSS 订阅(feed.xml)
└── 站点地图(sitemap.xml)不管是文章、项目还是动态,日期统一按北京时间(UTC+8)解析。凡是标了 draft: true 或者发布日期在未来的内容,在正式构建(dist/)里一律过滤掉;哪怕某篇公开文章关联了一个还在写草稿的项目,正式页面上也不会把那个草稿项目的入口暴露出来。
平时自己在本地写草稿想看效果时,就用单独的 pnpm dev:drafts 或 pnpm build:drafts(输出到独立的 dist-drafts/ 目录),和正式发布的产物彻底分开。
源码结构与资源按需加载
新站点的代码结构按职责分得很清楚:
| 目录 / 文件 | 作用 |
|---|---|
src/config、src/data | 站点基本信息、导航栏与分类预设 |
src/content.config.ts | 内容集合与 YAML 字段类型定义 |
src/lib | 发布过滤、排序、分类汇总、关联检查与 Markdown 处理 |
src/pages、src/layouts | 页面路由与布局模板 |
src/components | 独立 UI 组件 |
src/scripts | 浏览器端原生 JS 脚本 |
src/styles | 基础样式与各页面独立样式 |
以前旧站所有的交互都塞在一个全局脚本里,打开任何页面都要先跑一通 DOM 查询。现在改成组件脚本按需加载:只有文章里有 Mermaid 流程图或者打开了搜索框时,浏览器才会去请求对应的脚本;页面上的小图标也在构建阶段直接输出成内联 SVG,不用在浏览器里跑一套图标库。
接入 Pagefind 全文搜索
旧站的搜索只匹配截断后的文章摘要,经常搜不到正文里的命令或报错信息。迁移后我接入了 Pagefind,在 Astro 生成完静态 HTML 之后,直接扫描 dist 目录建立全文索引:
astro build
↓
生成静态 HTML 页面(dist/)
↓
pagefind --site dist
↓
生成按需加载的搜索索引分片这样平时看文章的时候完全不加载搜索资源,只有点开搜索框时才会按需拉取索引。需要注意的一点是,因为索引是在 build 阶段生成的,平时跑 pnpm dev 改样式时没法直接测正式搜索,测搜索要先 pnpm build 再 pnpm preview。
图片渲染与标题层级处理
整理旧文章时还遇到了两个小问题:
- 旧文章正文里有很多一级标题
#:为了不用挨篇去改旧文章的 Markdown 源码,我在 Markdown 渲染插件里加了一步处理,自动把正文里的标题往下降一级,保证整个网页只有文章大标题自己是唯一的<h1>。 - 不同比例的图片容易被裁坏:相机拍的照片、终端截图和宽屏界面比例差很多,如果强行居中裁剪很容易把边上的关键内容切掉。所以我做了一个通用的图片组件:前景完整显示原图,多出来的留白用同一张图片放大模糊后的背景铺底,看着自然又不会丢信息。
构建校验与维护流程
迁移完之后,每次改完代码或写完文章,跑下面这几条命令就能把类型、内容字段、单元测试和生成的 HTML 链接全检查一遍:
pnpm check
pnpm test
pnpm build
pnpm build:drafts旧的 Zola 源码我已经打包留了本地备份,以后就安心维护这套 Astro 源码了。现在写新文章不用再去猜字段怎么填,改页面也有测试兜底,比以前省心太多了。