# Mizuki 部署指南 本文档提供 Mizuki 博客在各个平台的部署配置说明。 ## 📖 目录 - [部署前准备](#-部署前准备) - [GitHub Pages 部署](#-github-pages-部署) - [Vercel 部署](#-vercel-部署) - [Netlify 部署](#-netlify-部署) - [Cloudflare Pages 部署](#-cloudflare-pages-部署) - [故障排查](#-故障排查) --- ## 🚀 部署前准备 ### 基础配置 1. **更新站点 URL** 编辑 `astro.config.mjs`: ```javascript export default defineConfig({ site: 'https://your-domain.com', // 更新为你的域名 // ... }); ``` 2. **配置环境变量** (可选) 如果使用内容分离功能,需要配置: - `ENABLE_CONTENT_SYNC=true` - `CONTENT_REPO_URL=你的内容仓库地址` - `USE_SUBMODULE=true` 详见 [内容分离完整指南](./CONTENT_SEPARATION.md) --- ## 📦 GitHub Pages 部署 ### 自动部署 (推荐) 项目已配置好 GitHub Actions 工作流,推送到 `main` 分支会自动部署。 #### 本地模式 (默认) **无需任何配置**,开箱即用: 1. 推送代码到 GitHub 2. 在仓库设置中启用 GitHub Pages - Settings → Pages - Source: Deploy from a branch - Branch: `pages` / `root` 3. 等待 Actions 完成部署 #### 内容分离模式 **配置步骤**: 1. **添加仓库 Secrets**: - Settings → Secrets and variables → Actions → New repository secret - 添加 `CONTENT_REPO_URL`: `https://github.com/your-username/Mizuki-Content.git` 2. **修改 `.github/workflows/deploy.yml`**: 取消注释环境变量部分: ```yaml - name: Build site run: pnpm run build env: ENABLE_CONTENT_SYNC: true CONTENT_REPO_URL: ${{ secrets.CONTENT_REPO_URL }} USE_SUBMODULE: true ``` 3. **私有内容仓库配置**: **同账号私有仓库** (推荐): - 无需额外配置 - 自动使用 `GITHUB_TOKEN` 访问 **跨账号私有仓库 (SSH)**: ```yaml # 添加 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)**: ```yaml - 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 部署 ### 快速部署 1. **连接仓库**: - 访问 [Vercel](https://vercel.com) - Import Git Repository - 选择你的 Mizuki 仓库 2. **配置项目**: - Framework Preset: Astro - Build Command: `pnpm build` (默认) - Output Directory: `dist` (默认) 3. **部署**: - 点击 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 部署 ### 部署步骤 1. **连接仓库**: - 访问 [Netlify](https://www.netlify.com) - New site from Git - 选择你的 Mizuki 仓库 2. **配置构建**: - Build command: `pnpm build` - Publish directory: `dist` 3. **环境变量** (如果使用内容分离): 在 Site settings → Environment variables 中添加: ``` ENABLE_CONTENT_SYNC=true CONTENT_REPO_URL=https://github.com/your-username/Mizuki-Content.git USE_SUBMODULE=true ``` 4. **私有仓库配置**: 在 Site settings → Build & deploy → Deploy key 中添加有权限访问私有仓库的 SSH 密钥。 ### netlify.toml 配置 可选:创建 `netlify.toml` 文件: ```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 部署 ### 部署步骤 1. **连接仓库**: - 登录 [Cloudflare Dashboard](https://dash.cloudflare.com) - Workers & Pages → Create application → Pages - Connect to Git 2. **配置构建**: - Framework preset: Astro - Build command: `pnpm build` - Build output directory: `dist` 3. **环境变量** (如果使用内容分离): 添加以下变量: ``` 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` --- ## 🔄 自动同步机制 所有部署平台都使用相同的自动同步机制: ```json // package.json { "scripts": { "prebuild": "node scripts/sync-content.js || true" } } ``` **工作原理**: 1. `pnpm build` 执行前自动运行 `prebuild` 钩子 2. 检查 `ENABLE_CONTENT_SYNC` 环境变量 3. 如果为 `true`,从远程仓库同步内容到 `src/content/` 和 `public/images/` 4. 如果为 `false` 或未设置,跳过同步,使用本地内容 5. `|| true` 确保同步失败不会中断构建 **优势**: - ✅ 统一的构建命令,无需修改配置 - ✅ 自动兼容所有部署模式 - ✅ 同步失败不影响构建(回退到本地内容) --- ## 🔍 故障排查 ### 问题 1: 部署失败 - "未设置 CONTENT_REPO_URL" **原因**: 启用了内容分离但未配置仓库地址 **解决**: 1. 检查环境变量中是否设置了 `ENABLE_CONTENT_SYNC=true` 2. 检查是否设置了 `CONTENT_REPO_URL` 3. 或将 `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/` 行: ```diff # 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 克隆失败 **检查**: 1. 确认部署平台支持 Git Submodule 2. 检查 SSH 密钥或 Token 配置 3. 尝试使用独立仓库模式: `USE_SUBMODULE=false` ### 问题 5: 构建成功但内容未更新 **检查**: 1. 查看构建日志,确认同步步骤执行 2. 检查 `ENABLE_CONTENT_SYNC` 是否设置为 `true` 3. 验证 `CONTENT_REPO_URL` 是否正确 4. 清除部署平台的缓存并重新部署 ### 问题 6: 部署时间过长 **优化建议**: - 使用 Git Submodule 模式 (更快) - 启用部署平台的缓存机制 - 优化图片大小和数量 ### 问题 7: Vercel 部署时 submodule 权限问题 **错误信息**: ``` fatal: could not read Username for 'https://github.com' ``` **原因**: 私有仓库需要认证 **解决**: 1. 在 Vercel 项目设置中添加 GitHub 集成权限 2. 或使用 Token: `https://${GITHUB_TOKEN}@github.com/user/repo.git` 3. 或切换到独立仓库模式: `USE_SUBMODULE=false` **检查**: 1. 查看构建日志,确认同步步骤执行 2. 检查 `ENABLE_CONTENT_SYNC` 是否设置为 `true` 3. 验证 `CONTENT_REPO_URL` 是否正确 4. 清除部署平台的缓存并重新部署 --- ## 📋 环境变量参考 | 变量名 | 必需 | 默认值 | 说明 | |-------|------|--------|------| | `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 认证 ### 多站点部署 - **平台**: 多个平台同时部署 - **模式**: 内容分离 - 公开仓库 - **配置**: 统一的环境变量配置 --- ## 📚 相关文档 - [内容分离完整指南](./CONTENT_SEPARATION.md) - 详细的内容分离配置 - [内容迁移指南](./MIGRATION_GUIDE.md) - 从单仓库迁移到分离模式 - [内容仓库结构](./CONTENT_REPOSITORY.md) - 内容仓库的组织方式 --- 💡 **建议**: 如果是第一次部署,推荐先使用本地模式熟悉流程,之后再根据需要启用内容分离功能。 ## 🔔 内容仓库更新触发构建 ### 问题说明 当使用**内容代码分离**架构时,默认情况下: - ✅ 代码仓库 (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)** 1. 访问 [GitHub Settings → Developer settings → Personal access tokens → Tokens (classic)](https://github.com/settings/tokens) 2. 点击 **Generate new token (classic)** 3. 配置 Token: - Note: `Mizuki Content Trigger` (名称随意) - Expiration: `No expiration` 或选择合适的期限 - Scopes: 勾选 `repo` (完整仓库访问权限) 4. 点击 **Generate token**,复制生成的 Token (只显示一次!) **Step 2: 在内容仓库添加 Secret** 1. 打开内容仓库 (Mizuki-Content): `https://github.com/your-username/Mizuki-Content` 2. Settings → Secrets and variables → Actions → New repository secret 3. 添加: - Name: `DISPATCH_TOKEN` - Value: 粘贴刚才创建的 PAT Token 4. 点击 **Add secret** **Step 3: 在内容仓库创建 GitHub Actions 工作流** 在内容仓库创建文件 `.github/workflows/trigger-build.yml`: ```yaml 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` 触发器: ```yaml name: Deploy to GitHub Pages on: push: branches: - main repository_dispatch: # 添加这个触发器 types: - content-updated # ...其余配置保持不变 ``` **Step 5: 测试** 1. 在内容仓库编辑一篇文章 2. 提交并推送到 `main` 分支 3. 查看内容仓库的 Actions 页面,确认 "Trigger Main Repo Build" 工作流运行 4. 查看代码仓库的 Actions 页面,确认部署工作流被触发 --- ### 方案 2: Webhook + Deploy Hook **原理**: 使用云平台提供的 Deploy Hook URL,在内容仓库更新时通过 webhook 触发构建。 **优点**: - ✅ 实时触发 - ✅ 与部署平台深度集成 **缺点**: - ⚠️ 需要为每个部署平台单独配置 - ⚠️ 不适用于 GitHub Pages #### Vercel 配置 **Step 1: 获取 Deploy Hook URL** 1. 打开 Vercel 项目设置 2. Settings → Git → Deploy Hooks 3. 创建新的 Hook: - Name: `Content Update` - Git Branch: `main` (或你的主分支) 4. 点击 **Create Hook**,复制生成的 URL **Step 2: 在内容仓库配置 Webhook** 在内容仓库创建 `.github/workflows/trigger-vercel.yml`: ```yaml 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** 1. 打开 Netlify 站点设置 2. Site settings → Build & deploy → Continuous deployment → Build hooks 3. 点击 **Add build hook**: - Build hook name: `Content Update` - Branch to build: `main` 4. 保存并复制生成的 URL **Step 2: 配置 GitHub Actions** 在内容仓库创建 `.github/workflows/trigger-netlify.yml`: ```yaml 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** 1. 打开 Cloudflare Pages 项目 2. Settings → Builds & deployments → Deploy hooks 3. 创建 Deploy Hook: - Hook name: `Content Update` - Branch: `main` 4. 保存并复制 URL **Step 2: 配置类似于 Vercel/Netlify** 配置方式与上述相同,只需修改 Secret 名称和 workflow 文件名。 --- ### 方案 3: 定时构建 (fallback) **原理**: 设置定时任务,每天自动构建一次。 **优点**: - ✅ 配置简单 - ✅ 无需额外 Token 或 Webhook **缺点**: - ⚠️ 有延迟,不是实时更新 - ⚠️ 可能造成不必要的构建 #### GitHub Actions 配置 在代码仓库的 `.github/workflows/deploy.yml` 中添加定时触发: ```yaml 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 设置定时构建: ```yaml # 在内容仓库创建 .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 }}" ``` --- ### 推荐配置组合 #### 最佳实践 (推荐) 结合多种方式,确保稳定性: ```yaml # 代码仓库 .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 - [ ] 创建了内容仓库的触发工作流 - [ ] 更新了代码仓库的部署工作流 - [ ] 测试了一次提交,确认触发成功 #### 测试步骤 1. **在内容仓库修改文章**: ```bash cd /path/to/Mizuki-Content # 编辑文章 git add . git commit -m "test: trigger build" git push ``` 2. **查看内容仓库 Actions**: - 访问 `https://github.com/your-username/Mizuki-Content/actions` - 确认 "Trigger Build" 工作流运行成功 3. **查看代码仓库 Actions**: - 访问 `https://github.com/your-username/Mizuki/actions` - 确认部署工作流被触发 - 查看日志确认内容同步成功 4. **查看部署平台**: - Vercel/Netlify/CF Pages: 查看部署历史 - GitHub Pages: 访问站点确认更新 --- ### 故障排查 #### 问题 1: 内容仓库推送后没有触发构建 **检查**: 1. 内容仓库的 Actions 是否运行? - 查看 Actions 页面,确认工作流被触发 2. PAT Token 权限是否正确? - 需要 `repo` 完整权限 3. 代码仓库名称是否正确? - 格式: `owner/repo` **调试**: ```yaml # 在内容仓库工作流中添加调试步骤 - name: Debug run: | echo "Repository: your-username/Mizuki" echo "Event type: content-updated" ``` #### 问题 2: Repository dispatch 触发成功但构建失败 **检查**: 1. 代码仓库的 Actions 是否启用? - Settings → Actions → General → 确保启用 2. 工作流文件是否包含 `repository_dispatch` 触发器? 3. 环境变量是否正确配置? #### 问题 3: PAT Token 过期 **现象**: 工作流运行失败,提示认证错误 **解决**: 1. 重新生成 PAT Token 2. 更新内容仓库的 Secret 3. 测试触发 #### 问题 4: Deploy Hook 无效 **检查**: 1. Hook URL 是否正确复制? 2. Secret 是否正确添加? 3. 使用 curl 测试 Hook: ```bash curl -X POST "https://api.vercel.com/v1/integrations/deploy/..." ``` ---