Skip to content

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_INSTALLtrue,在 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/_genresources/_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: 主要原因:

  1. 生成 3,341 个页面
  2. 569 本书内容
  3. 模板复杂度
  4. 没有充分利用缓存

通过启用缓存可以减少 10-20% 的时间。

Q3: 可以跳过 Worker 同步吗?

A: 可以,但不推荐。Worker 同步只需 6-7 秒,且确保数据实时性。如果需要跳过:

# 在 Cloudflare Pages 环境变量中设置
SYNC_ENABLED=false

Q4: 为什么不使用增量构建?

A: Hugo 目前不支持真正的增量构建。但可以通过:

  1. 良好的缓存策略
  2. Cloudflare Pages 的构建缓存
  3. 未来考虑自定义增量构建逻辑

总结

推荐实施顺序

  1. 第一步(立即):移除不必要的 Python 依赖(-60 秒)
  2. 第二步(本周):优化 Hugo 配置和缓存(-10 秒)
  3. 第三步(下周):优化文件输出和上传(-5 秒)
  4. 第四步(未来):考虑增量构建和架构优化

预期效果

  • 短期目标:从 ~185 秒降至 ~115-125 秒(减少 ~35-40%)
  • 中期目标:从 ~185 秒降至 110-120 秒(减少 ~35-40%)
  • 长期目标:从 ~185 秒降至 ~90 秒(减少 ~50%)

最重要的是移除不必要的 Python 依赖,这一项就能节省约 60 秒!