跳到正文
Victor BI
返回

我是如何组织并部署这个博客的

为什么写这篇

这个仓库不只是用来存放博客源码。它也记录了我希望这个博客如何被开发、构建和发布:源码应该放在哪里,Cloudflare 应该构建什么,以及哪些文件不应该成为事实来源。

这个项目的目标很简单:

仓库结构

这个项目没有直接放在仓库根目录,而是放在仓库的 src 目录下。

重要结构大概是这样:

repo-root/
├── README.md
├── .gitignore
└── src/
    ├── package.json
    ├── pnpm-lock.yaml
    ├── astro.config.ts
    ├── astro-paper.config.ts
    ├── public/
    └── src/
        ├── content/
        │   ├── pages/
        │   └── posts/
        │       ├── en/
        │       │   └── blog.md
        │       └── zh/
        │           └── blog.md
        ├── pages/
        ├── layouts/
        └── components/

这里会看到一个看起来有点奇怪的 src/src。但它其实是两个不同层级。

第一个 src 是 Cloudflare Pages 看到的项目根目录。它里面有 package.jsonastro.config.ts 和 lockfile。第二个 src 是站点源码目录,里面放页面、布局、组件和内容。

所以部署时,Cloudflare 应该进入:

repo-root/src

然后构建流程会把静态网站生成到:

repo-root/src/dist

因为 Cloudflare Pages 的项目根目录已经是 src,所以 Cloudflare 里的构建输出目录应该填写:

dist

而不是:

src/dist

这个区别很小,但它正是那种会让部署失败的细节。

源码和构建产物要分开

我希望 Git 跟踪的是网站源码,而不是已经生成出来的网站。

源码包括 Markdown 文章、页面、布局、组件、配置文件和 lockfile。构建产物则是执行 build 之后生成的 dist 目录。

所以这些目录不应该提交到 Git:

node_modules/
src/node_modules/
dist/
src/dist/
.wrangler/

根目录的 .gitignore 也保留了对旧构建输出目录的忽略,例如:

deploy/cloudflare/website/

这样仓库会更干净。如果需要重新发布网站,应该从源码重新构建,而不是把某次旧的构建产物当成事实来源。

本地开发

本地开发时,我会先进入应用目录:

cd src
pnpm install
pnpm dev

开发服务器会运行在:

http://localhost:4321/

这是我写文章、改布局、检查页面效果时的主要反馈循环。

本地构建

部署之前,我可以先在本地跑一次生产构建:

cd src
pnpm build

构建完成后会生成:

src/dist/

这个目录就是最终可以发布的静态网站。里面会包含 HTML、静态资源、RSS、sitemap、搜索索引,以及其他构建生成的文件。

为什么选择 Cloudflare Pages

一开始我思考的是:“怎样把静态文件放到 Cloudflare 上?”如果从这个角度出发,很容易走到 Worker 的方案。Worker 也确实可以托管静态资源。

但对这个博客来说,Cloudflare Pages 更合适。

它的心智模型更简单:

GitHub 仓库
Cloudflare Pages 构建
生成静态网站

这个项目本质上就是一个静态博客。我不需要为了说明它而额外维护一个 Worker 应用。Pages 对这种项目更直接。

两种部署方式

我为这个项目保留了两种部署方式。它们适合不同场景。

方式一:本地构建后用 Wrangler 上传

这种方式适合我想在本机完成构建,然后手动上传生成的 dist 目录。

命令流程是:

cd src
pnpm install
pnpm build
npx wrangler login
npx wrangler pages deploy dist --project-name=victorbi-preview --branch=main

这里使用 dist 是正确的,因为命令是在 src 这个应用目录里执行的。

这里的 --branch 选择的是 Cloudflare Pages 的部署环境上下文。它不一定等同于本地 Git 分支名。对这个仓库来说,手动上传路径指向的是 victorbi-preview 这个 Pages 项目。

方式二:让 Cloudflare 从 GitHub 构建

这是更适合作为长期方案的工作流。

发布流程变成:

撰写或修改文章
提交源码
推送到 GitHub
Cloudflare Pages 构建静态网站
Cloudflare Pages 部署 dist

这个仓库在 Cloudflare Pages 里的配置应该是:

Root directory:
src

Build command:
pnpm build

Build output directory:
dist

Node.js version:
22.12.0 or newer

Environment variable:
NODE_VERSION=22.12.0

Node 版本很重要,因为 src/package.json 里声明了这个要求:

{
  "engines": {
    "node": ">=22.12.0"
  }
}

如果 Cloudflare 使用更旧的 Node 版本构建,即使本地构建正常,线上构建也可能失败。

域名这个细节

站点配置里当前使用的是:

https://victorbi.pages.dev/

这个值在:

src/astro-paper.config.ts

手动部署目标是:

victorbi-preview

这个预览项目发布到:

https://victorbi-preview.pages.dev/

这里最重要的规则是:site.url 应该和我希望搜索引擎、RSS、sitemap、页面元数据使用的正式域名一致。如果生产环境的 Cloudflare Pages 域名变了,我也应该同步更新 src/astro-paper.config.ts

我如何组织双语文章

这个博客是双语的。英文文章放在:

src/src/content/posts/en/

中文文章放在:

src/src/content/posts/zh/

两种语言版本通过同一个 translationKey 关联:

translationKey: "deploy-blog"

每篇文章也会声明自己的语言:

lang: "en"

或者:

lang: "zh"

这样站点可以把英文和中文文章当作两个独立的 Markdown 文件处理,同时又知道它们属于同一篇文章的两个语言版本。

我的发布检查清单

当我修改内容时,检查流程应该尽量短:

cd src
pnpm build

如果构建成功,再提交并推送:

git add .
git commit -m "Update blog post"
git push

之后 Cloudflare Pages 可以从 GitHub 自动构建并部署。如果需要手动部署,也可以使用上面的 Wrangler 流程。

参考资料

这套部署会用到的 Cloudflare 文档包括:

对这个项目来说,这些链接是辅助资料。真正的实践来源仍然是仓库本身:src/package.json 说明脚本和 Node 版本要求,src/astro-paper.config.ts 说明站点元数据,Cloudflare Pages 项目设置说明实际部署行为。


分享这篇文章:

上一篇
AI 浪潮下,程序员的时代在悄悄变了
下一篇
欢迎来到 Victor BI