KernelRanch
返回文章列表

构建配置与缓存:让 Pages 每次构建都可复现

2026-11-10 #Cloudflare

读完这篇你能做到:把 Pages 的构建配置调到一个可复现的状态,知道每个字段影响什么,明白依赖缓存省下的时间从哪来,并且在"本地能构建、云端失败"时有一份确定的排查顺序。

适用的场景是 Git 集成方式部署,也就是云端执行构建命令的那条路径。用 wrangler pages deploy 直接传产物的,构建发生在你自己的机器或 CI 上,这篇里的环境变量一节仍然值得看一眼。

1. 四个核心字段

字段作用常见错误
Root directory命令在哪个目录执行仓库是 monorepo,填了根目录导致找不到 package.json
Build command安装依赖之外的构建动作把 npm install 也写进去,和平台的自动安装重复
Build output directory上传哪个目录写成源码目录,把 src 也传了上去
Build watch paths只有这些路径变化才触发构建留空,改文档也触发一次构建

Root directory 在 monorepo 里最容易出问题。仓库结构是 apps/web 加 packages/ui 时,根目录要填 apps/web,输出目录填 dist(相对根目录),而不是 apps/web/dist。

Build command 里不需要写 npm install。平台在跑构建命令之前会自己装依赖,重复写一次只会让构建变慢;除非你要装的是平台识别不到的东西。

Build watch paths 是省构建次数的开关。一个仓库里既有站点又有文档时,把它设成 src/* 之类,改 README 就不会消耗那 500 次月度额度。

2. Node 版本与包管理器

平台按 lock 文件判断包管理器:有 pnpm-lock.yaml 用 pnpm,有 yarn.lock 用 yarn,有 package-lock.json 用 npm。三种文件同时存在时行为取决于平台的探测顺序,删掉多余的最省事。

Node 版本用环境变量固定:

NODE_VERSION=20

不写也能构建,但默认版本会随平台镜像更新而变。某天构建突然因为某个依赖要求更高版本而挂掉,通常就是这里没锁。

pnpm 项目还要注意版本:packageManager 字段写进 package.json 比在环境变量里指定更稳。

3. 两类环境变量别混

类型何时可用是否会暴露
构建时变量只在构建容器里会被打进产物,前端代码能读到
Functions 变量与密钥只在请求处理时不出现在产物里

把 API key 配成构建时变量,再在前端代码里 import.meta.env 读出来,等于把它公开在 JS 文件里。需要在浏览器里调第三方接口时,走服务端代理,密钥留在 Functions 的 context.env 里,写法见 68-pages-functions.md。

变量按环境区分:Production 与 Preview 各有一套。预览环境指向测试接口、生产环境指向正式接口,靠的就是这个区分。

4. 依赖缓存

平台会在多次构建之间保留依赖缓存,装过的包不必每次从 registry 重新下载。这就是为什么第一次构建要两三分钟,后续改动只改一个组件时可能几十秒就结束。

缓存命中依赖两件事:lock 文件没变、包管理器版本没变。改了 pnpm-lock.yaml 就会重新装一遍,这是正常现象,不是缓存失效。

缓存不覆盖构建产物。dist 每次都是新生成的,不存在"上次的旧文件混进来"的情况。

5. 分支不同,命令不同

预览环境需要和生产不同的构建参数时(比如预览站要开调试面板、指向测试 API),在项目 Settings 的 Builds & deployments 里可以给指定分支单独配命令与变量。

配置粒度是分支名,不是通配。分支命名建议固定成 main、dev、preview/* 这样的规则,配起来才不会漏。

6. 构建失败时的排查顺序

按这个顺序看,多数问题在前两步就能定位。

  1. 读构建日志的最后 30 行,找第一个 ERROR,不是最后一个。
  2. 本地用同样的 Node 版本跑一次 npm run build。对不上就是环境差异。
  3. 检查大小写。Linux 构建环境区分大小写,import './Header' 在 Windows 上能过,云端会失败,而本地文件名是 header.vue。
  4. 检查 lock 文件是否提交进了仓库。没有 lock 文件时依赖版本可能和本地不一致。
  5. 检查输出目录是否存在。构建成功但目录为空,部署上去就是 404。

第 3 条是最常见的隐性原因。本地开发在 Windows 或 macOS 默认文件系统上不区分大小写,这个问题只在云端暴露。

常见问题

某次提交不想触发构建,怎么做。

在 commit message 里带上 [skip ci],平台会跳过这次构建。适合只改注释或文档、又不想占用月度额度的提交。

构建时要用私有 npm 包。

在仓库里放 .npmrc,把 registry 和认证 token 配好。token 建议放构建时环境变量而不是提交进仓库,.npmrc 里用变量引用。

为什么同一份代码两次构建结果不一样。

检查是否有依赖没锁版本(^ 开头的依赖加上无 lock 文件)、构建时是否读了当前时间或随机数、以及是否依赖了本地存在的文件但没提交。这三类都会让构建不可复现。

小结

构建配置的目标只有一个:让云端那次构建和你在本地跑出来的结果一致。做到这一点靠四件事,锁 Node 版本、提交 lock 文件、输出目录填对、变量分对环境。

依赖缓存是加速手段,不是正确性保障。它省掉的是下载时间,省不掉环境差异带来的问题,所以排查顺序里第三步永远是本地复现。

框架侧的具体命令(Astro 的 dist、Hugo 的 public)在 71-static-site-astro-hugo.md,构建额度与并发的完整对照在 56-free-tier-limits-cheatsheet.md。

数据来源与检索时间

检索时间 2026-11-10。

来源URL对应数据
Pages Limitshttps://developers.cloudflare.com/pages/platform/limits/免费档每月 500 次构建、并发 1、单次构建 20 分钟超时
Pages 构建配置文档https://developers.cloudflare.com/pages/configuration/build-configuration/根目录、构建命令、输出目录、监视路径、NODE_VERSION 环境变量
Pages 分支构建配置https://developers.cloudflare.com/pages/configuration/branch-build-controls/按分支设置不同构建命令与变量

核验说明

  • 文档部分:构建次数与超时来自 2026-11-10 抓取的 Pages Limits 页面。字段含义与 NODE_VERSION 用法依据官方构建配置文档。
  • 未执行:没有 Pages 项目,所有控制台配置项(根目录、监视路径、分支构建)未实际操作。
  • 未执行:依赖缓存的实际命中效果未观测,缓存保留时长与容量未在文档中查到明确数字,因此正文没有给出具体时长。
  • 未执行:[skip ci] 未在真实仓库验证,依据官方文档描述。
  • 本地构建验证:无。这篇讨论平台侧配置,本机没有对应的构建产物可验证。