2026年8月8日 星期六 晴→雷雨
此刻窗外正在打雷,即将到来的台风风级很大。
今天下午和晚上都在重构博客的部署系统,最终从 Bitbucket Pipelines 迁移到了 GitHub Actions。
问题背景
我大概有 3500+ 篇博客,历史部署经历过三个阶段:
阶段一:本地编译,推静态文件到 Git
本地 hugo --gc 编译成 HTML,连同源文件一起推 git 仓库。一开始没事,后来 git 仓库越来越大,最终 overflow。
阶段二:Vercel 构建 改为 Vercel 原生构建,本地只推源文件。Vercel 有时 1‑2 分钟成功,有时直接跑到 45m 被杀掉。原因是 Vercel 构建缓存最大 1GB,超过或长时间不部署会被驱逐,触发全量冷构建。4000 页面属于中大型 Hugo 站点,冷构建压力大,日志滚动到无响应,超时被杀。
阶段三:Bitbucket Pipelines 构建 + Vercel 托管静态文件
构建放到 Bitbucket(2x 内存,4GB),hugo --gc 后把 public/ 产物通过 Vercel CLI 上传。Vercel 只做文件分发,不跑编译。这个方案当天就遇到了问题:上传 4473 个文件逐个请求,网络通畅时 2 分钟,堵车时 9 分钟+。而且 Bitbucket 免费版每月只有 50 构建分钟,调试几次后直接耗尽。
最终方案:GitHub Actions
免费版私有仓库 2000 分钟/月,是 Bitbucket 的 40 倍。公共仓库更是无限分钟。
1. 工作流文件
创建 .github/workflows/deploy.yml,逻辑与之前的 Bitbucket pipeline 一致:
name: Build & Deploy to Vercel
on:
push:
branches: [master]
workflow_dispatch: # 支持手动触发
jobs:
build-and-deploy:
runs-on: ubuntu-latest # 4GB 内存,够用
steps:
- uses: actions/checkout@v4
- name: Install Hugo
run: |
wget -q "https://github.com/gohugoio/hugo/releases/download/v0.101.0/hugo_extended_0.101.0_Linux-64bit.tar.gz" -O /tmp/hugo.tar.gz
tar -xzf /tmp/hugo.tar.gz -C /usr/local/bin/ hugo
hugo version
- name: Build site
env:
HUGO_CACHEDIR: ${{ github.workspace }}/.hugo_cache
run: hugo --gc
- name: Install Vercel CLI
run: npm install -g vercel
# 配 project 设置:buildCommand: null, outputDirectory: "."
- name: Configure Vercel project
run: ... # 通过 API 配置
- name: Deploy to Vercel
run: |
vercel ./public --prod --archive=tgz \
--token=$VERCEL_TOKEN --scope=$VERCEL_ORG_ID --project=$VERCEL_PROJECT_ID
2. 关键优化:--archive=tgz
vercel ./public --prod 默认把 4473 个文件逐个上传,每个文件一次 HTTP 请求。加 --archive=tgz 后,Vercel CLI 将全部文件打包成单个 tgz 上传,一次请求搞定。Vercel 官方文档明确说"当部署包含数千个文件时使用此选项"。
3. Vercel 端配置
与 Bitbucket 方案时一致,不需要改动:
- 构建命令为空(
buildCommand: null) - 输出目录为
.(上传的目录就是构建产物)
4. 仓库变量
在 GitHub 仓库 Settings → Secrets and variables → Actions 中配置:
| 变量名 | 说明 |
|---|---|
VERCEL_TOKEN |
Vercel 账号 Token |
VERCEL_ORG_ID |
Team ID |
VERCEL_PROJECT_ID |
项目 ID |
踩坑记录
| 问题 | 原因 | 修复 |
|---|---|---|
Vercel CLI --org 报错 |
58 版本弃用 --org |
改为 --scope |
找不到 public 输出目录 |
Vercel 收到文件后又跑构建 | 加 --prebuilt 参数 |
--prebuilt 需要 .vercel/output 结构 |
--prebuilt 期望 vercel build 格式 |
改用 API 配置项目:buildCommand: null + outputDirectory: ".",不加 --prebuilt 直部署 |
| 上传 4473 个文件耗时 2~9+ 分钟不稳定 | 逐个文件 HTTP 上传,网络波动影响大 | --archive=tgz 打包为单文件上传 |
| Bitbucket 免费版构建分钟耗尽 | 每月 50 分钟,调试几次就用完 | 迁移到 GitHub Actions(2000 分钟/月) |
| GitHub 无法连接 | 国内网络环境 | Clash 代理 + git 只对 github.com 设代理,不影响公司内网 |
最终效果
- 本地编写 →
git push→ GitHub Actions 自动构建(Hugo 0.101.0,4GB runner,15s)→--archive=tgz打包上传 Vercel(几十秒) - 不再受 Vercel 构建缓存驱逐影响,构建时间稳定
- 不再受 CI 分钟配额限制,2000 分钟/月随便用
- 本地不再推
public/目录,git 仓库大幅缩小 - 部署流程完全通过
git push触发,写文章的工作流没变
总结
从 Vercel 构建 → Bitbucket Pipelines → GitHub Actions,每次迁移都是在解决上一个方案的瓶颈。最终选择 GitHub Actions 的理由很硬:私有仓库 2000 分钟/月、4GB 免费 runner 够用、与 Vercel 之间的网络路径稳定。加上 --archive=tgz 解决了文件上传的瓶颈,整个部署链路不再有不可控的环节。
希望靠谱吧,以后还是混github。
...