Cloudflare Pages 部署 Vite 项目踩坑记

场景

把一个 React + Vite + TypeScript 项目部署到 Cloudflare Pages (Git integration 自动构建模式), 上传 push 触发构建日志一直炸:

npmcinpm ci npmci npm run build

▎ vite build

sh: 1: vite: not found npm ERR! Lifecycle "build" didn't pass "exec".

错误 vite: not found 但本地 npm run build 一切正常, GitHub Actions CI 也正常. 怎么 CF Pages 独立环境挂?

排查一路, 最后根因有点意外: CF Pages 默认环境变量 NODE_ENV=production, 而 npm ci 在此模式下会跳过 devDependencies, 导致 vite 根本没装.

排查过程

被 "vite: not found" 误导阶段

一开始以为:

  1. CF Pages 没装 Node 或版本太低 --- 排查, Node 20 OK
  2. package.json 缺 vite 依赖 --- 检查 package.json:
json 复制代码
"devDependencies": {
  "vite": "^5.2.11",
  "husky": "^9.0.11",
  "@vitejs/plugin-react-swc": "^3.7.0",
  "vitest": "^1.6.0"
}

vite 在 devDependencies. 一般情况下 npm ci 会装 devDeps. 但是...

关键诊断: packages 数量不对

让构建日志输出 packages 总数:

$ npm ci
added 449 packages in 12s

449 个 packages. 而本地 npm install 后看 node_modules:

$ ls node_modules | wc -l
1019

差 570 个 --- 配 devDeps 全没了.

真凶: NODE_ENV=production 会让 npm 跳过 devDependencies

查 npm 文档 npm-install docs (https://docs.npmjs.com/cli/v9/commands/npm-install):

▎ If NODE_ENV is set to production at install time, npm will not install modules listed in devDependencies.

CF Pages 默认注入 NODE_ENV=production, 触发 npm 这个优化分支 → devDeps 跳过 → vite 没装 → build 时 vite build 找不到 binary → 报
vite: not found.

而 GitHub Actions CI 默认 NODE_ENV 不设, Vercel 默认 NODE_ENV 不设, EdgeOne 默认也不设, 独独 CF Pages 默认生产环境变量化.
这就解释同样 lockfile 同样 package.json, 仅 CF 炸.

三个解决方案

方案 A: 给 CF Pages 加 NODE_ENV=development

CF Pages 项目 → Settings → Environment Variables → 加一条 NODE_ENV = development.

缺点:整个构建环境全程 NODE_ENV=development, vite build 时某些 optimization 不会触发 (例如 mode=production 默认逻辑), build 出
bundle 没压缩. 不推荐.

方案 B: 给 CF Pages 加 NPM_CONFIG_PRODUCTION=false

CF Pages 项目 → Settings → Environment Variables → 加一条 NPM_CONFIG_PRODUCTION=false. 同样语义但比 A 干净, 不污染 NODE_ENV.

生效: npm 会忽略 production 模式, 装 devDeps. 但整个环境标记也会让其他 tooling (不检 NODE_ENV 直接检 npm_config_production)
误判以为开发模式.

中等推荐. 临时方案.

方案 C: 加 .npmrc 配置 include=dev ✅ (推荐)

最干净. 项目根新建 public/.npmrc 或仓库根 .npmrc:

include=dev

.npmrc 中 include=dev 强制 npm不论 NODE_ENV 都装 devDependencies. 不动 CF Pages 环境变量, 不污染 NODE_ENV. 也不影响本地开发 ---
本地 NODE_ENV 通常不设, npm 默认装 devDeps.

CF Pages 二次构建, packages 数从 449 涨到 1019:

$ npm ci
added 1019 packages in 22s

vite, husky, vitest 全装上. npm run build 跑通 365 个静态文件生成, CF Pages 上传成功.

补充坑

坑 1: prepare 脚本里的 husky 找不到

package.json:
"prepare": "husky install"

npm 在生产环境自动跑 prepare 钩子, 但 husky 也没装 (husky 也是 devDep). 改:

"prepare": "husky install || true"

加 || true 让 husky 找不到也不阻断构建.

坑 2: binlink 缺失 / alternative binary 找不到

部分 CF Pages 版本上 npm 装了 vite 但 node_modules/.bin/vite 软链丢了, npm run build 调 vite 仍找不到. 临时解决:

"scripts": {
  "build": "tsc && vite build",
  "build:cf": "node node_modules/vite/bin/vite.js build"
}

build:cf 直接走 node node_modules/vite/bin/vite.js 入口 JS, 绕过 bin 软链. CF Pages 后台 Build Command 设 npm run build:cf.

但随着 .npmrc 修复 sort 出来后 binlink 也正常, 这条不必再加. 留下笔记备查.

坑 3: package-lock.json 顶部 name 必须跟 package.json 匹配

老 fork 项目 package.json 改过 name 但 lockfile 没重生, CF Pages 报 ERR_PNPM_OUTDATED_LOCKFILE 或类似.

重生 lockfile:

npm install --package-lock-only
git add package-lock.json
git commit -m "chore: regenerate package-lock.json"
git push

CF Pages 重新构建 lockfile 跟 package.json 同步.

结论

CF Pages 默认 NODE_ENV=production 对常规 React/Vite 工程是个陷阱:

┌───────────────┬────────────────┬──────────────────────────┐
│     阶段      │      行为      │           问题           │
├───────────────┼────────────────┼──────────────────────────┤
│ npm ci        │ 跳过 devDeps   │ vite, vitest, husky 不装 │
├───────────────┼────────────────┼──────────────────────────┤
│ npm run build │ 调 vite binary │ not found                │
├───────────────┼────────────────┼──────────────────────────┤
│ 上传          │ 静态文件 0     │ 部署失败                 │
└───────────────┴────────────────┴──────────────────────────┘

加项目根 .npmrc 一行 include=dev 解决, 不污染环境变量, 不改 build 命令.

示例项目: ToolKit (https://xbot.ink) --- 在 CF Pages 部署的项目, 100+ 免费在线工具 + 10 语言.

扩充源码 (含 .npmrc, _redirects, CF 部署配置): (https://github.com/crazy-choose/toolkit-additions)
相关推荐
尼斯湖皮皮怪1 小时前
iceCoder 记忆系统深度分析
前端·javascript
谢尔登1 小时前
通过Semi Design思考前端组件AI化
前端·人工智能
小蚂蚁i1 小时前
把 TypeScript 内置工具类型彻底搞懂,顺便自己封几个好用的
前端·typescript
维基框架1 小时前
当Prompt编辑变成训练过程:SkillOpt的逆直觉方案
前端
KaMeidebaby1 小时前
卡梅德生物技术快报|小 RNA 适配体合成 + 多方法亲和力表征全流程标准化操作手册
前端·网络·数据库·人工智能·算法
OpenTiny社区2 小时前
Coding Agent 到底是怎么工作的,它又为什么会在复杂代码库里失真?
前端·github·agent
奇奇怪怪的2 小时前
Graph RAG:知识图谱增强检索
前端
默_笙2 小时前
🌏 MCP 是 AI 界的 USB-C:一个协议让所有模型都能用上所有工具
前端·javascript
以和为贵2 小时前
🔥前端也能搞懂流式输出:从 SSE 到打字机效果
前端·人工智能·架构