记录从多站点文档系统迁移到纯博客的完整过程,以及遇到的各种坑和解决方案。
背景
之前用 Mintlify 搭建了一个多站点文档管理系统(doc-manager),维护了多个子站点的文档。但实际需求变了——只需要一个个人博客。
决定弃用文档站点,专注博客,把仓库改造成 Astro 个人博客。
迁移方案
核心思路:仓库根目录直接就是 Astro 项目,不走多站点构建管线。
最简原则:一个博客、一个仓库、一条部署链路。
踩坑记录
坑 1:astro check 扫描了构建产物
CI 的 astro check 把 output/ 目录里压缩后的 JS 文件也当 TypeScript 检查了,报了几十个错误。
解决方案:在 tsconfig.json 中排除 scripts/、output/、dist/ 目录。
{
"exclude": ["scripts/*", "output/*", "dist/*", "node_modules/*"]
}
坑 2:部署时 SSL 证书不存在
Nginx 配置引用了 Let’s Encrypt 证书,但新域名 blog.waterflow.site 还没有签发证书,Nginx 直接启动失败。
解决方案:临时改用 webroot 模式签发证书,签发后再恢复 HTTPS 配置。
# 1. 临时配置允许 ACME 挑战
# 2. certbot certonly --webroot -w /var/www/certbot -d blog.waterflow.site
# 3. 恢复完整 HTTPS 配置
同时更新了 CI 部署脚本,以后新增域名自动签发证书。
坑 3:workflow_dispatch 不触发部署
CI 的 deploy job 条件是 github.run_number == 1,只在第一次运行成立。手动触发时 deploy 被跳过。
解决方案:改为 workflow_dispatch 始终触发,push 时 commit 消息含 “deploy” 也触发。
坑 4:PageFind 搜索全透明
这是最折磨的一个坑。搜索 modal 打开后背景全透明,内容完全看不清。
根本原因:Pagefind 的 CSS 文件通过 <link> 动态加载,在外部 <style> 之后生效,覆盖了我们的样式。
尝试过的方法:
| 尝试 | 结果 |
|---|---|
| 外部 <style> 覆盖 | Pagefind CSS 加载后覆盖回来 |
| 加 !important | 选择器权重不够,匹配不到动态插入的元素 |
| 用 .dark 选择器 | 暗色模式能部分生效,亮色模式仍然透明 |
最终解决方案:在加载 Pagefind CSS 之前,先用 JS 注入内联 <style> 标签,确保 !important 规则在所有 CSS 之后生效。
var style = document.createElement('style');
style.textContent = `
.pagefind-ui { background: #fff !important; color: #171717 !important; }
.dark .pagefind-ui { background: #171717 !important; color: #e5e5e5 !important; }
.pagefind-ui input { color: #171717 !important; }
.dark .pagefind-ui input { color: #e5e5e5 !important; }
`;
document.head.appendChild(style);
// 然后再加载 Pagefind CSS
var link = document.createElement('link');
link.rel = 'stylesheet';
link.href = '/pagefind/pagefind-ui.css';
document.head.appendChild(link);
关键:内联 <style> 在 <link> 之前注入,但因为是 JS 动态创建的,实际上在 DOM 中排在 <link> 之后,所以能覆盖。
坑 5:部署链路过于臃肿
原来的 CI 有 15 个步骤,包括 artifact 中转、Umami 部署等。实际上:
| 步骤 | 是否需要 |
|---|---|
| Inject meta tags | 不需要,Umami 已硬编码到模板 |
| Generate sitemap | 不需要,Astro 内置 @astrojs/sitemap |
| Generate nginx config | 不需要,只有 1 个站点,直接写死 |
| Umami 部署 | 不需要,Umami 已稳定运行 |
| Artifact 中转 | 不需要,直接 SCP |
简化后只剩 6 步:checkout → setup bun → install → type check → build → deploy。
最终成果
| 项目 | 状态 |
|---|---|
| HTTPS | Let’s Encrypt 证书,自动续签 |
| SEO | Sitemap、OG 图像、JSON-LD 全自动 |
| 搜索 | PageFind,亮色/暗色模式正常 |
| 分析 | Umami 自托管 |
| 部署 | 每次 push 自动部署 |
| CI | 6 步,约 45 秒完成 |
总结:最小化是最好的架构。一个博客、一条部署链路、没有多余的中间环节。