这篇文章解决什么问题

很多个人博客卡住,不是因为不会搭站,而是因为发布链路太重。每写一篇文章都要手工改配置、手工构建、手工上传,久而久之内容生产就断掉了。

我这次把自己的博客整理成一条更顺手的流程:本地直接写 Markdown,提交到 GitHub 后由 GitHub Actions 自动构建和发布。这样写文章这件事,才更像持续做内容,而不是每次都做一次运维。

适用场景

  • 你做的是个人博客、技术内容站或轻量文档站
  • 你希望文章以 Markdown 文件保存在仓库里
  • 你不想上 WordPress,也不想维护重后台
  • 你希望中英双语内容能长期维护,而不是靠手工映射

如果你更想要在线后台、多人协作编辑和可视化审核流,那这套方式就不是最优解。

最终效果

这套链路跑通之后,发一篇新文章只需要这几步:

  1. 本地生成中英双语文章骨架
  2. 编辑两份 Markdown
  3. 本地预览确认内容和排版
  4. git push origin main
  5. GitHub Actions 自动部署上线

也就是说,内容生产和部署已经被拆开了。你只关心写文章,发布动作由自动化接手。

环境准备

我当前这套博客栈是:

  • 框架:Astro
  • 内容层:astro:content
  • 内容格式:Markdown
  • 部署方式:静态产物发布
  • Web 服务:Nginx
  • 自动部署:GitHub Actions

内容目录是双语分开的:

src/content/posts/zh-cn/*.md
src/content/posts/en-us/*.md

同一篇文章的中英文文件共享一个 path,站点会自动生成:

  • 中文:/posts/<path>/
  • 英文:/en/posts/<path>/

具体步骤

1. 先把内容模型定死

如果一开始内容模型不稳定,后面你每加一篇文章都要补逻辑。

我现在把博客的文章、页面、分类、资源都统一放进了 astro:content,关键点有两个:

  • 文章用 path
  • 页面和分类用 key

这样做的好处是,新增内容时只增加 Markdown 文件,不再去碰路由映射代码。

2. 提供一个文章脚手架命令

如果每次发文章都手工复制旧文件,效率很快就会下降。

我在项目里补了一个脚本:

npm run new:post -- "markdown-blog-publish-workflow" "本地写 Markdown,git push 后自动上线:我的双语博客发布流程" "Write Markdown Locally, Deploy on git push: My Bilingual Blog Publishing Workflow" writing

执行后会直接生成两份草稿:

src/content/posts/zh-cn/markdown-blog-publish-workflow.md
src/content/posts/en-us/markdown-blog-publish-workflow.md

默认是:

draft: true

这很重要,因为它能防止你写到一半就被自动部署出去。

3. 本地只负责写作和预览

写文章时,我只做两件事:

  1. 编辑 Markdown
  2. 本地 npm run dev

浏览器里主要看这些点:

  • 首页是否出现新文章
  • 中文和英文详情页是否都可访问
  • 分类和标签是否正常聚合
  • 标题和描述是否适合 SEO

如果这一步通过,后面其实就不该再手工 SSH 发布了。

4. 把部署动作交给 GitHub Actions

这一步是整个流程能不能真正省事的关键。

我现在的工作流是:

  1. push 到 main
  2. Actions 自动 npm ci
  3. 自动 npm run build
  4. 打包 dist
  5. 通过 SSH 上传服务器
  6. 解压到新的 releases/<timestamp>-<sha>
  7. 切换 current
  8. 做一次公网可访问性校验

这意味着文章发布已经变成标准 CI/CD 流程,而不是依赖我手工操作。

5. 生产服务器只做静态托管

我的一个明确原则是:服务器不负责构建,只负责托管。

这样有几个直接好处:

  • 服务器更稳定
  • 构建环境更统一
  • 回滚更简单
  • 出问题时能快速分层定位

目前线上结构大概是:

/var/www/aitokenhacks.com/releases/<release-id>
/var/www/aitokenhacks.com/current

每次发布都只是在切换软链接,不是覆盖线上目录。

6. 给自动部署补诊断信息

自动化不是写完 workflow 就结束了。真正有用的自动化,出错时要能快速说明白问题。

所以我后来又给 workflow 补了几类诊断:

  • 缺少哪个 Deploy Secret
  • SSH 是否能连通
  • 远端目录是否存在
  • current 最终切到了哪个 release

这样以后如果部署失败,不会只看到一个抽象的红叉,而是能很快知道问题是在 GitHub Secrets、SSH、目录权限,还是公网验证。

常见问题

为什么我不直接上在线后台

因为我现在这个站的重点是内容积累和 SEO,而不是编辑器体验。

Markdown 文件化管理有几个我更看重的优点:

  • 全量进入 Git
  • 可回滚
  • 可审阅
  • 内容和代码结构一致
  • 不依赖第三方后台可用性

双语内容为什么不用单文件混写

因为单文件里塞两套 frontmatter 和两套正文,维护成本很快会上来。

我最后选的是“双文件,同 path”的方式:

  • 符合 Astro 内容集合的天然工作方式
  • 正文维护最直观
  • 不需要额外翻译映射层

自动部署失败最常见的原因是什么

我这次实际踩到过的主要有两类:

  • GitHub Actions 计费或额度问题,作业直接起不来
  • Deploy Secrets 没配对,SSH 配置阶段直接失败

所以我现在会优先检查:

  1. Actions 是否真的开始执行
  2. Secrets 是否齐
  3. SSH 用户和密钥是否有效
  4. 远端目录权限是否允许发布

最后总结

如果你也在做个人技术博客,我非常建议把“写作”和“发布”拆开。

写作时,只管内容质量。 发布时,让 CI/CD 去做重复动作。

当你能把发文动作压缩成“本地写 Markdown,然后 git push”,内容站才真正进入可持续维护的状态。