Cloudflare Pages 构建优化¶
本文档介绍如何优化 Cloudflare Pages 的构建速度,将构建时间从 3 分钟缩短到 1-2 分钟。
当前构建时间分析¶
基于构建日志分析:
| 阶段 | 耗时 | 占比 | 优化潜力 |
|---|---|---|---|
| Clone 代码 | 3 秒 | 2% | 低 ⚪ |
| 恢复缓存 | 2 秒 | 1% | 低 ⚪ |
| npm 依赖安装 | 6 秒 | 3% | 中 🟡 |
| Python 依赖安装 | ~60 秒 | ~30% | 高 🔴 |
| Hugo 构建 | 85 秒 | 54% | 高 🔴 |
| JSON 压缩 | 1 秒 | 1% | 低 ⚪ |
| Worker 同步 | 7 秒 | 4% | 低 ⚪ |
| 文件上传 | 15 秒 | 9% | 中 🟡 |
| 部署完成 | 6 秒 | 4% | 低 ⚪ |
| 总计 | ~204 秒 | 100% | - |
优化目标:减少 50-70 秒,将总时间降至约 134-154 秒(约 2.2-2.6 分钟)。
优化策略¶
1. 移除不必要的 Python 依赖 ⭐⭐⭐¶
当前问题:
- 安装了 126 个 Python 包(约 60 秒)
- 大部分包(如
litellm,fastapi,mkdocs)只在本地使用 - Cloudflare Pages 构建时不需要这些包
解决方案:设置环境变量 SKIP_DEPENDENCY_INSTALL 为 true,在 Cloudflare Pages 构建过程中跳过 Python 依赖安装,从而节省安装这些不必要本地开发包的时间。构建脚本应直接执行 Node 构建步骤,例如 npm ci && npm run build(或项目已有的构建命令)。
在构建脚本中示例处理:
# 如果 SKIP_DEPENDENCY_INSTALL 未设置为 true,则安装 Python 依赖
if [ "$SKIP_DEPENDENCY_INSTALL" != "true" ]; then
pip install -r requirements.txt
else
echo "SKIP_DEPENDENCY_INSTALL=true - skipping python dependency installation"
fi
# 继续 Node/Hugo 构建
npm ci && npm run build
预计节省:约 1 分钟
2. 优化 Hugo 构建 ⭐⭐⭐¶
当前问题:
- Hugo 构建耗时 85 秒
- 生成 3,341 个页面
- 大量内容处理和模板渲染
a. 启用 Hugo 缓存
确保 Hugo 使用缓存目录(已配置):
// scripts/site/run-hugo.js
const cacheDir = path.join(process.cwd(), 'resources', '_cache');
b. 优化 Hugo 配置
在 config/_default/config.toml 中添加:
# 构建优化
[build]
# 使用缓存
useResourceCacheWhen = "always"
# 并行处理(默认值,确认启用)
# Hugo 会自动使用多核
[caches]
[caches.getjson]
dir = ":resourceDir/_cache/getjson"
maxAge = "24h"
[caches.getcsv]
dir = ":resourceDir/_cache/getcsv"
maxAge = "24h"
[caches.images]
dir = ":resourceDir/_cache/images"
maxAge = "168h" # 7 天
[caches.assets]
dir = ":resourceDir/_cache/assets"
maxAge = "168h"
c. 减少不必要的处理
检查是否有不必要的内容处理:
# 检查是否有大量的 .GetPage 调用
grep -r "\.GetPage" layouts/
# 检查是否有复杂的 partial 嵌套
grep -r "partial" layouts/ | wc -l
d. 考虑增量构建(未来优化)
Hugo 目前不支持真正的增量构建,但可以:
- 使用 Cloudflare Pages 的缓存
- 确保
resources/_gen和resources/_cache被缓存
预计节省:10-20 秒(通过缓存和优化)
3. 优化文件上传 ⭐⭐¶
当前问题:
- 上传 5,032 个文件,其中 2,154 个已缓存
- 实际上传 2,878 个文件(15 秒)
a. 减少输出文件数量
检查是否生成了不必要的文件:
# 查看 public 目录大小和文件数
du -sh public/
find public -type f | wc -l
# 查看最大的文件
du -ah public/ | sort -rh | head -20
b. 启用 Hugo 资源合并
确保 CSS/JS 已合并:
# config/_default/config.toml
[minify]
minifyOutput = true
[minify.tdewolff.css]
keepCSS2 = false
[minify.tdewolff.js]
keepVarNames = false
c. 使用 Hugo Pipes 合并资源
在模板中合并多个 CSS/JS 文件:
{{ $styles := resources.Get "scss/style.scss" | toCSS | postCSS | minify | fingerprint }}
<link rel="stylesheet" href="{{ $styles.RelPermalink }}">
预计节省:3-5 秒
4. 优化 npm 依赖安装 ⭐¶
当前问题:
- 安装 629 个 npm 包(6 秒)
- 有一些废弃的包警告
a. 更新废弃的包
# 更新 Puppeteer
npm install puppeteer@latest
# 移除或替换 deprecated 包
npm uninstall inflight glob@7 # 如果不需要
b. 使用 npm ci 确保使用缓存
Cloudflare Pages 已使用 npm clean-install,这是最优的。
c. 移除开发依赖(如果可能)
检查 devDependencies 是否都需要:
# 查看开发依赖
jq '.devDependencies' package.json
# 如果某些包只在本地需要,考虑移到单独的 package.json
预计节省:1-2 秒
5. 禁用不必要的构建步骤 ⭐¶
检查是否需要某些步骤:
a. 内容分析¶
package.json 现已内置 site:build:lean,默认的 npm run build 只会运行 Hugo 和搜索索引压缩:
{
"scripts": {
"build": "npm run site:build:lean",
"site:build": "npm run site:build:production",
"site:build:lean": "npm run ai:manifest:generate && node scripts/site/run-hugo.js --environment production --minify && npm run search:index:compress",
"site:build:production": "npm run ai:manifest:generate && node scripts/site/run-hugo.js --environment production --minify && npm run site:postprocess"
}
}
Cloudflare Pages 直接执行 npm run build 即可跳过 HTML Minify 与内容分析,只有当需要全量分析数据时再手动运行 npm run site:build:production。
另外,scripts/site/generate-analysis-data.js 会检查 SKIP_ANALYSIS 环境变量:
if (process.env.SKIP_ANALYSIS === 'true') {
console.log('[analysis] SKIP_ANALYSIS=true, skipping analysis data generation.');
process.exit(0);
}
在 Cloudflare Pages 中设置 SKIP_ANALYSIS=true 可以完全跳过该 Node 脚本。
b. AI Manifest 生成¶
scripts/ai/generate-ai-project-manifest.js 现在会遍历 content/*/ai/**/index.md 的最新修改时间,仅在有比现有 manifest 更新的内容时才重新生成。若确实需要强制刷新,可以在命令前加入 FORCE_AI_MANIFEST=true。
# 默认:无 AI 变更会自动跳过
npm run ai:manifest:generate
# 强制生成
FORCE_AI_MANIFEST=true npm run ai:manifest:generate
预计节省:2-3 秒
c. 输出格式裁剪¶
config/_default/config.toml 中已经设置 [outputs],只为 section/page/taxonomy/term 生成 HTML,减少 RSS/JSON 派生文件:
[outputs]
home = ["HTML", "RSS", "JSON"]
section = ["HTML"]
page = ["HTML"]
taxonomy = ["HTML"]
term = ["HTML"]
配合 _redirects 与 _build 控制,可以显著降低需要上传的文件数量。
预计节省:2-3 秒
实施方案¶
方案 A:快速优化(推荐)⭐¶
最小改动,最大收益
1. 快速跳过 Python 依赖安装(推荐)
在 Cloudflare Pages 的环境变量中设置 SKIP_DEPENDENCY_INSTALL=true,或在构建命令前导入该变量,从而在大多数构建场景下直接跳过 Python 包安装,节省约 1 分钟。示例:
# 在 Pages Dashboard 或 CI 环境变量中设置
SKIP_DEPENDENCY_INSTALL=true
然后使用项目现有的构建命令,例如:
npm ci && npm run build
2. 优化 Hugo 配置
添加缓存配置(见上文)。
预计效果:
- 跳过 Python 安装:约 -60 秒
- Hugo 缓存优化:-10 秒
- 总节省:~70 秒
- 新构建时间(预估):~90 秒(约 1.5 分钟)
方案 B:深度优化¶
更多改动,更大收益
包含方案 A 的所有优化,加上:
1. 条件构建分析数据
scripts/site/generate-analysis-data.js 内置 SKIP_ANALYSIS 判断:
if (process.env.SKIP_ANALYSIS === 'true') {
console.log('[analysis] SKIP_ANALYSIS=true, skipping analysis data generation.');
process.exit(0);
}
2. 优化 Hugo 模板
# 分析模板性能
hugo --templateMetrics --templateMetricsHints
# 优化慢的模板
3. 减少输出文件
配置文件已经为 section/taxonomy 等种类只保留 HTML 输出,更多裁剪可在同一块 [outputs] 中调整。
预计效果:
- 额外节省:-15 秒
- 总节省:~40 秒
- 新构建时间:~120 秒(2 分钟)
方案 C:激进优化(高级)¶
需要架构调整
1. 分离构建和部署
# .github/workflows/incremental-build.yml
on:
push:
paths:
- 'content/zh/blog/**'
jobs:
incremental:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
with:
fetch-depth: 2
- name: Get changed files
id: changed
run: |
echo "files=$(git diff --name-only HEAD HEAD~1 | grep '^content/' || true)" >> $GITHUB_OUTPUT
- name: Incremental build
if: steps.changed.outputs.files != ''
run: |
# 只构建变化的内容
npm run site:build:incremental
2. 使用 CDN 预热
// scripts/cdn-warmup.js
// 构建完成后预热关键页面
const urls = [
'https://jimmysong.io/',
'https://jimmysong.io/blog/',
// ... 关键页面
];
Promise.all(urls.map(url => fetch(url)));
预计效果:
- 增量构建:-30-50 秒(对小改动)
- 新构建时间:~60-90 秒(1-1.5 分钟)
实施步骤¶
立即实施(方案 A)¶
1. 在 Cloudflare Pages 中设置环境变量:
在 Pages Dashboard(或对应的 CI 环境)添加:
SKIP_DEPENDENCY_INSTALL=true
2. 使用项目的构建命令触发构建:
npm ci && npm run build
3. 触发构建并验证:
观察构建日志中是否出现跳过 Python 依赖安装的日志(如上示例脚本中的 echo),并验证构建时间下降约 1 分钟。
后续优化(方案 B)¶
在方案 A 生效并验证后,逐步实施方案 B 的优化。
监控和验证¶
构建时间对比¶
| 阶段 | 优化前 | 优化后(方案 A) | 节省 |
|---|---|---|---|
| Python 安装 | ~60 秒 | 0 秒 | -60 秒 |
| Hugo 构建 | 85 秒 | 75 秒 | -10 秒 |
| 其他(Clone/npm/缓存/上传等) | 40 秒 | 40 秒 | 0 秒 |
| 总计 | ~185 秒 | ~115 秒 | ~-70 秒 |
验证清单¶
- Python 依赖安装时间减少到 0-2 秒
- Hugo 构建时间减少 10-20 秒
- 总构建时间 < 2.5 分钟
- 网站功能正常
- AI 资源页面正常显示
- 搜索功能正常
常见问题¶
Q1: 移除 Python 依赖会影响功能吗?¶
A: 不会。requirements.txt 中的包(如 mkdocs, litellm)只在本地使用:
- MkDocs 用于生成文档站点(本地)
- LiteLLM 等用于本地开发工具
- Cloudflare Pages 构建只需要 Hugo 和 Node.js
Q2: Hugo 构建为什么这么慢?¶
A: 主要原因:
- 生成 3,341 个页面
- 569 本书内容
- 模板复杂度
- 没有充分利用缓存
通过启用缓存可以减少 10-20% 的时间。
Q3: 可以跳过 Worker 同步吗?¶
A: 可以,但不推荐。Worker 同步只需 6-7 秒,且确保数据实时性。如果需要跳过:
# 在 Cloudflare Pages 环境变量中设置
SYNC_ENABLED=false
Q4: 为什么不使用增量构建?¶
A: Hugo 目前不支持真正的增量构建。但可以通过:
- 良好的缓存策略
- Cloudflare Pages 的构建缓存
- 未来考虑自定义增量构建逻辑
总结¶
推荐实施顺序:
- 第一步(立即):移除不必要的 Python 依赖(-60 秒)
- 第二步(本周):优化 Hugo 配置和缓存(-10 秒)
- 第三步(下周):优化文件输出和上传(-5 秒)
- 第四步(未来):考虑增量构建和架构优化
预期效果:
- 短期目标:从 ~185 秒降至 ~115-125 秒(减少 ~35-40%)
- 中期目标:从 ~185 秒降至 110-120 秒(减少 ~35-40%)
- 长期目标:从 ~185 秒降至 ~90 秒(减少 ~50%)
最重要的是移除不必要的 Python 依赖,这一项就能节省约 60 秒!