20 KiB
Mizuki 部署指南
本文档提供 Mizuki 博客在各个平台的部署配置说明。
📖 目录
🚀 部署前准备
基础配置
- 更新站点 URL
编辑 astro.config.mjs:
export default defineConfig({
site: 'https://your-domain.com', // 更新为你的域名
// ...
});
- 配置环境变量 (可选)
如果使用内容分离功能,需要配置:
ENABLE_CONTENT_SYNC=trueCONTENT_REPO_URL=你的内容仓库地址USE_SUBMODULE=true
详见 内容分离完整指南
📦 GitHub Pages 部署
自动部署 (推荐)
项目已配置好 GitHub Actions 工作流,推送到 main 分支会自动部署。
本地模式 (默认)
无需任何配置,开箱即用:
- 推送代码到 GitHub
- 在仓库设置中启用 GitHub Pages
- Settings → Pages
- Source: Deploy from a branch
- Branch:
pages/root
- 等待 Actions 完成部署
内容分离模式
配置步骤:
-
添加仓库 Secrets:
- Settings → Secrets and variables → Actions → New repository secret
- 添加
CONTENT_REPO_URL:https://github.com/your-username/Mizuki-Content.git
-
修改
.github/workflows/deploy.yml:
取消注释环境变量部分:
- name: Build site
run: pnpm run build
env:
ENABLE_CONTENT_SYNC: true
CONTENT_REPO_URL: ${{ secrets.CONTENT_REPO_URL }}
USE_SUBMODULE: true
- 私有内容仓库配置:
同账号私有仓库 (推荐):
- 无需额外配置
- 自动使用
GITHUB_TOKEN访问
跨账号私有仓库 (SSH):
# 添加 SSH 配置步骤
- name: Setup SSH Key
uses: webfactory/ssh-agent@v0.8.0
with:
ssh-private-key: ${{ secrets.SSH_PRIVATE_KEY }}
- name: Checkout
uses: actions/checkout@v4
with:
submodules: true
在 Secrets 中添加:
SSH_PRIVATE_KEY: SSH 私钥内容CONTENT_REPO_URL:git@github.com:other-user/repo.git
跨账号私有仓库 (Token):
- name: Checkout
uses: actions/checkout@v4
with:
submodules: true
token: ${{ secrets.PAT_TOKEN }}
- name: Build site
run: pnpm run build
env:
ENABLE_CONTENT_SYNC: true
CONTENT_REPO_URL: https://${{ secrets.PAT_TOKEN }}@github.com/other-user/repo.git
USE_SUBMODULE: true
在 Secrets 中添加:
PAT_TOKEN: GitHub Personal Access Token (需要repo权限)
工作流说明
项目包含三个工作流:
| 工作流 | 触发条件 | 功能 |
|---|---|---|
build.yml |
Push/PR 到 main | CI 测试,检查构建 |
deploy.yml |
Push 到 main | 构建并部署到 pages 分支 |
biome.yml |
Push/PR | 代码格式和质量检查 |
🔷 Vercel 部署
快速部署
-
连接仓库:
- 访问 Vercel
- Import Git Repository
- 选择你的 Mizuki 仓库
-
配置项目:
- Framework Preset: Astro
- Build Command:
pnpm build(默认) - Output Directory:
dist(默认)
-
部署:
- 点击 Deploy 开始部署
部署模式
本地模式
无需配置环境变量,使用默认的 vercel.json。
内容分离模式 - 公开仓库
在 Vercel 项目设置中添加环境变量:
| 变量名 | 值 |
|---|---|
ENABLE_CONTENT_SYNC |
true |
CONTENT_REPO_URL |
https://github.com/your-username/Mizuki-Content.git |
USE_SUBMODULE |
false 或 true (推荐 false) |
⚠️ 重要提示: 如果使用
USE_SUBMODULE=true,请确保.gitignore中的content/行已被注释掉,否则会导致部署失败。推荐在 Vercel 上使用USE_SUBMODULE=false(独立仓库模式)。
内容分离模式 - 私有仓库
方式 A: 授权 Vercel 访问
- 在连接 GitHub 仓库时,确保授权包括内容仓库的访问权限
方式 B: 使用 Token
添加环境变量:
ENABLE_CONTENT_SYNC=true
GITHUB_TOKEN=ghp_your_personal_access_token
CONTENT_REPO_URL=https://${GITHUB_TOKEN}@github.com/your-username/Mizuki-Content-Private.git
USE_SUBMODULE=true
配置文件
项目包含两个 Vercel 配置文件:
vercel.json- 默认配置,适用于本地模式vercel-with-content.json.example- 内容分离示例 (可选)
注意: 使用默认 vercel.json 即可,通过环境变量控制是否启用内容分离。
🌐 Netlify 部署
部署步骤
-
连接仓库:
- 访问 Netlify
- New site from Git
- 选择你的 Mizuki 仓库
-
配置构建:
- Build command:
pnpm build - Publish directory:
dist
- Build command:
-
环境变量 (如果使用内容分离):
在 Site settings → Environment variables 中添加:
ENABLE_CONTENT_SYNC=true
CONTENT_REPO_URL=https://github.com/your-username/Mizuki-Content.git
USE_SUBMODULE=true
- 私有仓库配置:
在 Site settings → Build & deploy → Deploy key 中添加有权限访问私有仓库的 SSH 密钥。
netlify.toml 配置
可选:创建 netlify.toml 文件:
[build]
command = "pnpm build"
publish = "dist"
[build.environment]
NODE_VERSION = "20"
PNPM_VERSION = "9"
# 如果使用内容分离
ENABLE_CONTENT_SYNC = "true"
CONTENT_REPO_URL = "https://github.com/your-username/Mizuki-Content.git"
USE_SUBMODULE = "true"
☁️ Cloudflare Pages 部署
部署步骤
-
连接仓库:
- 登录 Cloudflare Dashboard
- Workers & Pages → Create application → Pages
- Connect to Git
-
配置构建:
- Framework preset: Astro
- Build command:
pnpm build - Build output directory:
dist
-
环境变量 (如果使用内容分离):
添加以下变量:
ENABLE_CONTENT_SYNC=true
CONTENT_REPO_URL=https://github.com/your-username/Mizuki-Content.git
USE_SUBMODULE=false # ⚠️ Cloudflare Pages 默认不支持 submodule
注意事项
⚠️ Cloudflare Pages 默认不支持 Git Submodule,建议:
- 使用独立仓库模式:
USE_SUBMODULE=false - 或在构建命令中手动初始化:
git submodule update --init && pnpm build
🔄 自动同步机制
所有部署平台都使用相同的自动同步机制:
// package.json
{
"scripts": {
"prebuild": "node scripts/sync-content.js || true"
}
}
工作原理:
pnpm build执行前自动运行prebuild钩子- 检查
ENABLE_CONTENT_SYNC环境变量 - 如果为
true,从远程仓库同步内容到src/content/和public/images/ - 如果为
false或未设置,跳过同步,使用本地内容 || true确保同步失败不会中断构建
优势:
- ✅ 统一的构建命令,无需修改配置
- ✅ 自动兼容所有部署模式
- ✅ 同步失败不影响构建(回退到本地内容)
🔍 故障排查
问题 1: 部署失败 - "未设置 CONTENT_REPO_URL"
原因: 启用了内容分离但未配置仓库地址
解决:
- 检查环境变量中是否设置了
ENABLE_CONTENT_SYNC=true - 检查是否设置了
CONTENT_REPO_URL - 或将
ENABLE_CONTENT_SYNC设置为false使用本地内容
问题 2: 私有仓库认证失败
GitHub Actions:
- 同账号: 确保使用
${{ secrets.GITHUB_TOKEN }} - 跨账号: 配置 SSH 密钥或 PAT Token
Vercel/Netlify:
- 确保授权了私有仓库访问
- 或使用 Token 方式:
https://TOKEN@github.com/user/repo.git
问题 3: Submodule 与 .gitignore 冲突
错误信息:
The following paths are ignored by one of your .gitignore files:
content
fatal: Failed to add submodule 'content'
原因: .gitignore 文件中的 content/ 规则阻止了 Git 添加 submodule
解决方案 A: 修改 .gitignore (推荐)
编辑 .gitignore 文件,注释掉或删除 content/ 行:
# content repository (if using independent mode)
- content/
+ # content/ # 使用 submodule 时需要注释掉
*.backup
然后重新部署。
解决方案 B: 使用独立仓库模式
如果不想修改 .gitignore,可以使用独立仓库模式:
ENABLE_CONTENT_SYNC=true
CONTENT_REPO_URL=https://github.com/your-username/Mizuki-Content.git
USE_SUBMODULE=false # 改为 false
解决方案 C: 自动降级 (v1.1+)
sync-content.js 会自动检测此冲突并降级到独立仓库模式,无需手动干预。
问题 4: Submodule 克隆失败
检查:
- 确认部署平台支持 Git Submodule
- 检查 SSH 密钥或 Token 配置
- 尝试使用独立仓库模式:
USE_SUBMODULE=false
问题 5: 构建成功但内容未更新
检查:
- 查看构建日志,确认同步步骤执行
- 检查
ENABLE_CONTENT_SYNC是否设置为true - 验证
CONTENT_REPO_URL是否正确 - 清除部署平台的缓存并重新部署
问题 6: 部署时间过长
优化建议:
- 使用 Git Submodule 模式 (更快)
- 启用部署平台的缓存机制
- 优化图片大小和数量
问题 7: Vercel 部署时 submodule 权限问题
错误信息:
fatal: could not read Username for 'https://github.com'
原因: 私有仓库需要认证
解决:
- 在 Vercel 项目设置中添加 GitHub 集成权限
- 或使用 Token:
https://${GITHUB_TOKEN}@github.com/user/repo.git - 或切换到独立仓库模式:
USE_SUBMODULE=false
检查:
- 查看构建日志,确认同步步骤执行
- 检查
ENABLE_CONTENT_SYNC是否设置为true - 验证
CONTENT_REPO_URL是否正确 - 清除部署平台的缓存并重新部署
📋 环境变量参考
| 变量名 | 必需 | 默认值 | 说明 |
|---|---|---|---|
ENABLE_CONTENT_SYNC |
❌ | false |
是否启用内容分离功能 |
CONTENT_REPO_URL |
⚠️ | - | 内容仓库地址 (启用内容分离时必需) |
USE_SUBMODULE |
❌ | false |
是否使用 Git Submodule 模式 |
CONTENT_DIR |
❌ | ./content |
内容目录路径 |
UMAMI_API_KEY |
❌ | - | Umami 统计 API 密钥 |
BCRYPT_SALT_ROUNDS |
❌ | 12 |
bcrypt 加密轮数 |
⚠️ = 在特定模式下必需
💡 推荐配置
个人博客
- 平台: Vercel 或 GitHub Pages
- 模式: 本地模式(最简单)
- 配置: 无需环境变量
团队协作
- 平台: 任意
- 模式: 内容分离 - 私有仓库
- 配置: 启用内容分离 + SSH 认证
多站点部署
- 平台: 多个平台同时部署
- 模式: 内容分离 - 公开仓库
- 配置: 统一的环境变量配置
📚 相关文档
💡 建议: 如果是第一次部署,推荐先使用本地模式熟悉流程,之后再根据需要启用内容分离功能。
🔔 内容仓库更新触发构建
问题说明
当使用内容代码分离架构时,默认情况下:
- ✅ 代码仓库 (Mizuki) 更新会触发自动构建
- ❌ 内容仓库 (Mizuki-Content) 更新不会触发构建
这意味着您在内容仓库中发布新文章后,需要手动触发代码仓库的重新部署才能看到更新。
解决方案概览
有以下几种方式实现内容仓库更新时自动触发构建:
| 方案 | 难度 | 推荐度 | 适用平台 |
|---|---|---|---|
| Repository Dispatch | ⭐ 简单 | ⭐⭐⭐⭐⭐ | GitHub Pages, Vercel, Netlify, CF Pages |
| Webhook + Deploy Hook | ⭐⭐ 中等 | ⭐⭐⭐⭐ | Vercel, Netlify, CF Pages |
| 定时构建 | ⭐ 简单 | ⭐⭐⭐ | 所有平台 |
方案 1: Repository Dispatch (推荐)
原理: 内容仓库推送时,通过 GitHub Actions 触发代码仓库的构建工作流。
优点:
- ✅ 实时触发,无延迟
- ✅ 无需云平台特定配置
- ✅ 适用于所有部署平台
- ✅ 完全免费
配置步骤
Step 1: 创建 GitHub Personal Access Token (PAT)
- 访问 GitHub Settings → Developer settings → Personal access tokens → Tokens (classic)
- 点击 Generate new token (classic)
- 配置 Token:
- Note:
Mizuki Content Trigger(名称随意) - Expiration:
No expiration或选择合适的期限 - Scopes: 勾选
repo(完整仓库访问权限)
- Note:
- 点击 Generate token,复制生成的 Token (只显示一次!)
Step 2: 在内容仓库添加 Secret
- 打开内容仓库 (Mizuki-Content):
https://github.com/your-username/Mizuki-Content - Settings → Secrets and variables → Actions → New repository secret
- 添加:
- Name:
DISPATCH_TOKEN - Value: 粘贴刚才创建的 PAT Token
- Name:
- 点击 Add secret
Step 3: 在内容仓库创建 GitHub Actions 工作流
在内容仓库创建文件 .github/workflows/trigger-build.yml:
name: Trigger Main Repo Build
on:
push:
branches:
- main # 或你使用的主分支名称
paths:
- 'posts/**'
- 'spec/**'
- 'data/**'
- 'images/**'
jobs:
trigger:
runs-on: ubuntu-latest
steps:
- name: Trigger repository dispatch
uses: peter-evans/repository-dispatch@v2
with:
token: ${{ secrets.DISPATCH_TOKEN }}
repository: your-username/Mizuki # 改为你的代码仓库
event-type: content-updated
client-payload: |
{
"ref": "${{ github.ref }}",
"sha": "${{ github.sha }}",
"message": "${{ github.event.head_commit.message }}"
}
注意事项:
- 将
your-username/Mizuki替换为你的代码仓库完整名称 - 可以根据需要调整
paths,只在特定文件变化时触发
Step 4: 在代码仓库更新 GitHub Actions 工作流
编辑代码仓库的 .github/workflows/deploy.yml,添加 repository_dispatch 触发器:
name: Deploy to GitHub Pages
on:
push:
branches:
- main
repository_dispatch: # 添加这个触发器
types:
- content-updated
# ...其余配置保持不变
Step 5: 测试
- 在内容仓库编辑一篇文章
- 提交并推送到
main分支 - 查看内容仓库的 Actions 页面,确认 "Trigger Main Repo Build" 工作流运行
- 查看代码仓库的 Actions 页面,确认部署工作流被触发
方案 2: Webhook + Deploy Hook
原理: 使用云平台提供的 Deploy Hook URL,在内容仓库更新时通过 webhook 触发构建。
优点:
- ✅ 实时触发
- ✅ 与部署平台深度集成
缺点:
- ⚠️ 需要为每个部署平台单独配置
- ⚠️ 不适用于 GitHub Pages
Vercel 配置
Step 1: 获取 Deploy Hook URL
- 打开 Vercel 项目设置
- Settings → Git → Deploy Hooks
- 创建新的 Hook:
- Name:
Content Update - Git Branch:
main(或你的主分支)
- Name:
- 点击 Create Hook,复制生成的 URL
Step 2: 在内容仓库配置 Webhook
在内容仓库创建 .github/workflows/trigger-vercel.yml:
name: Trigger Vercel Deployment
on:
push:
branches:
- main
paths:
- 'posts/**'
- 'spec/**'
- 'data/**'
- 'images/**'
jobs:
trigger:
runs-on: ubuntu-latest
steps:
- name: Trigger Vercel Deploy Hook
run: |
curl -X POST "${{ secrets.VERCEL_DEPLOY_HOOK }}"
Step 3: 添加 Secret
在内容仓库添加 Secret:
- Name:
VERCEL_DEPLOY_HOOK - Value: 粘贴 Vercel Deploy Hook URL
Netlify 配置
Step 1: 获取 Build Hook URL
- 打开 Netlify 站点设置
- Site settings → Build & deploy → Continuous deployment → Build hooks
- 点击 Add build hook:
- Build hook name:
Content Update - Branch to build:
main
- Build hook name:
- 保存并复制生成的 URL
Step 2: 配置 GitHub Actions
在内容仓库创建 .github/workflows/trigger-netlify.yml:
name: Trigger Netlify Deployment
on:
push:
branches:
- main
paths:
- 'posts/**'
- 'spec/**'
- 'data/**'
- 'images/**'
jobs:
trigger:
runs-on: ubuntu-latest
steps:
- name: Trigger Netlify Build Hook
run: |
curl -X POST -d '{}' "${{ secrets.NETLIFY_BUILD_HOOK }}"
Step 3: 添加 Secret
- Name:
NETLIFY_BUILD_HOOK - Value: 粘贴 Netlify Build Hook URL
Cloudflare Pages 配置
Step 1: 获取 Deploy Hook URL
- 打开 Cloudflare Pages 项目
- Settings → Builds & deployments → Deploy hooks
- 创建 Deploy Hook:
- Hook name:
Content Update - Branch:
main
- Hook name:
- 保存并复制 URL
Step 2: 配置类似于 Vercel/Netlify
配置方式与上述相同,只需修改 Secret 名称和 workflow 文件名。
方案 3: 定时构建 (fallback)
原理: 设置定时任务,每天自动构建一次。
优点:
- ✅ 配置简单
- ✅ 无需额外 Token 或 Webhook
缺点:
- ⚠️ 有延迟,不是实时更新
- ⚠️ 可能造成不必要的构建
GitHub Actions 配置
在代码仓库的 .github/workflows/deploy.yml 中添加定时触发:
name: Deploy to GitHub Pages
on:
push:
branches:
- main
schedule:
- cron: '0 2 * * *' # 每天凌晨 2 点 (UTC 时间)
workflow_dispatch: # 支持手动触发
# ...其余配置
Cron 表达式示例:
0 2 * * *- 每天凌晨 2 点0 */6 * * *- 每 6 小时一次0 0 * * 1- 每周一凌晨
Vercel/Netlify 配置
这些平台也支持通过 webhook 设置定时构建:
# 在内容仓库创建 .github/workflows/scheduled-build.yml
name: Scheduled Build
on:
schedule:
- cron: '0 2 * * *'
workflow_dispatch:
jobs:
trigger:
runs-on: ubuntu-latest
steps:
- name: Trigger Deploy
run: |
curl -X POST "${{ secrets.DEPLOY_HOOK_URL }}"
推荐配置组合
最佳实践 (推荐)
结合多种方式,确保稳定性:
# 代码仓库 .github/workflows/deploy.yml
on:
push:
branches:
- main
repository_dispatch: # 内容更新触发
types:
- content-updated
schedule: # 兜底方案
- cron: '0 2 * * *'
workflow_dispatch: # 手动触发
优势:
- ✅ 内容更新实时触发 (repository_dispatch)
- ✅ 每天自动同步,防止遗漏 (schedule)
- ✅ 支持手动触发调试 (workflow_dispatch)
验证配置
检查清单
- 创建了 PAT Token 或 Deploy Hook
- 在内容仓库添加了对应的 Secret
- 创建了内容仓库的触发工作流
- 更新了代码仓库的部署工作流
- 测试了一次提交,确认触发成功
测试步骤
-
在内容仓库修改文章:
cd /path/to/Mizuki-Content # 编辑文章 git add . git commit -m "test: trigger build" git push -
查看内容仓库 Actions:
- 访问
https://github.com/your-username/Mizuki-Content/actions - 确认 "Trigger Build" 工作流运行成功
- 访问
-
查看代码仓库 Actions:
- 访问
https://github.com/your-username/Mizuki/actions - 确认部署工作流被触发
- 查看日志确认内容同步成功
- 访问
-
查看部署平台:
- Vercel/Netlify/CF Pages: 查看部署历史
- GitHub Pages: 访问站点确认更新
故障排查
问题 1: 内容仓库推送后没有触发构建
检查:
- 内容仓库的 Actions 是否运行?
- 查看 Actions 页面,确认工作流被触发
- PAT Token 权限是否正确?
- 需要
repo完整权限
- 需要
- 代码仓库名称是否正确?
- 格式:
owner/repo
- 格式:
调试:
# 在内容仓库工作流中添加调试步骤
- name: Debug
run: |
echo "Repository: your-username/Mizuki"
echo "Event type: content-updated"
问题 2: Repository dispatch 触发成功但构建失败
检查:
- 代码仓库的 Actions 是否启用?
- Settings → Actions → General → 确保启用
- 工作流文件是否包含
repository_dispatch触发器? - 环境变量是否正确配置?
问题 3: PAT Token 过期
现象: 工作流运行失败,提示认证错误
解决:
- 重新生成 PAT Token
- 更新内容仓库的 Secret
- 测试触发
问题 4: Deploy Hook 无效
检查:
- Hook URL 是否正确复制?
- Secret 是否正确添加?
- 使用 curl 测试 Hook:
curl -X POST "https://api.vercel.com/v1/integrations/deploy/..."