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/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
{
"scripts": {
"build": "npm run clean:cache && npm run generate:ai-manifest && node scripts/run-hugo.js --environment production --minify && npm run compress-json",
"build:full": "npm run clean:cache && npm run generate:ai-manifest && npm run generate-analysis && node scripts/run-hugo.js --environment production --minify && npm run compress-json"
}
}
配置 Cloudflare Pages 使用 npm run build
而不是 npm run build:full
。
b. AI Manifest 生成¶
如果 manifest 变化不频繁:
// 只在 AI 内容变化时生成
const fs = require('fs');
const glob = require('glob');
const aiFiles = glob.sync('content/*/ai/*/index.md');
const manifestMtime = fs.statSync('static/data/ai-projects-manifest.json').mtime;
const needsUpdate = aiFiles.some(f => fs.statSync(f).mtime > manifestMtime);
if (needsUpdate) {
// 生成 manifest
} else {
console.log('Manifest up to date, skipping generation');
}
预计节省: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/conditional-build.js
const shouldGenerateAnalysis = process.env.SKIP_ANALYSIS !== 'true';
if (shouldGenerateAnalysis) {
require('./generate-analysis-data.js');
}
2. 优化 Hugo 模板
# 分析模板性能
hugo --templateMetrics --templateMetricsHints
# 优化慢的模板
3. 减少输出文件
# 禁用不需要的输出格式
[outputs]
home = ["HTML", "RSS", "JSON"] # 只保留必要的
section = ["HTML"] # 移除不必要的格式
预计效果:
- 额外节省:-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 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 秒!