8.3 KiB
依赖问题排查指南
本文档记录本项目在依赖安装与启动过程中的实际问题、根因与解决方案。
项目环境基线
| 项 | 值 |
|---|---|
| 包管理器 | pnpm 11.17.0(唯一,仓库只有 pnpm-lock.yaml,无 package-lock.json) |
| Node | v22.23.1 |
| 构建工具 | Rspack 1.7.12(经 @cqsjjb/scripts 驱动) |
| 开发端口 | 8080(定义在 jjb.config.js) |
| 启动命令 | npm run serve:development |
| pnpm 配置文件 | pnpm-workspace.yaml(项目已无 .npmrc) |
最重要的一条:本项目使用 pnpm 11。pnpm 11 不再从
.npmrc读取public-hoist-pattern、hoist、node-linker等安装配置,这些配置已迁移到pnpm-workspace.yaml,并改用小驼峰命名(publicHoistPattern、nodeLinker)。项目原有的.npmrc因此完全失效,已被删除。
1. Unable to resolve loader babel-loader — loader 未被提升
这是本项目实际遇到的唯一阻塞启动的错误。
现象
ERROR in × Unable to resolve loader babel-loader??ruleSet[1].rules[2].use[0]
1 ERROR in child compilations
Rspack 1.7.12 compiled with 2 errors
根因
babel-loader 是 @cqsjjb/scripts 的传递依赖,并未写在本项目 package.json 中。pnpm 默认采用隔离式(isolated)node_modules 布局,传递依赖只存在于 node_modules/.pnpm/ 虚拟存储中,不会出现在顶层。Rspack 解析 loader 时按名称在顶层查找,因而失败。
项目原本试图用 .npmrc 的 public-hoist-pattern[]=*loader 解决,但如上所述,pnpm 11 已不读取该文件。可用以下命令验证配置是否真正生效:
pnpm config get public-hoist-pattern # 失效时返回 undefined
解决方案
在 pnpm-workspace.yaml 中声明 publicHoistPattern:
publicHoistPattern:
- '*loader*'
- '*webpack-plugin*'
- 'react-refresh'
- '@babel/*'
- 'postcss'
- 'autoprefixer'
注意通配符要写成 *loader* 而非 *loader,确保能匹配 babel-loader、css-loader 等带连字符的包名。
修改后必须重新安装才能生效(见下方「配置变更后如何让安装生效」)。
验证
@('babel-loader','style-loader','css-loader','less-loader','react-refresh','html-webpack-plugin') |
ForEach-Object { "$_ : " + (Test-Path "node_modules/$_") }
全部为 True 即成功。正常情况下 node_modules 顶层目录数约为 44 个(未提升时为 32 个)。
2. ERR_PNPM_IGNORED_BUILDS — build scripts 被忽略
现象
[ERR_PNPM_IGNORED_BUILDS] Ignored build scripts: @parcel/watcher, core-js, es5-ext,
x-data-spreadsheet, zy-react-library
Run "pnpm approve-builds" to pick which dependencies should be allowed to run scripts.
根因
pnpm v10+ 出于安全考虑,默认禁止依赖执行 postinstall 等 build scripts,需显式放行。
项目 pnpm-workspace.yaml 中原先写的是 allowBuilds,且值为占位文本 set this to true or false,属于无效配置。
解决方案
改用 onlyBuiltDependencies 数组格式,并删除无效的 allowBuilds 块:
onlyBuiltDependencies:
- '@parcel/watcher'
- core-js
- es5-ext
- x-data-spreadsheet
- zy-react-library
若安装后警告仍然出现,显式执行一次重建即可:
pnpm rebuild @parcel/watcher core-js es5-ext x-data-spreadsheet zy-react-library
该报错会让
pnpm install以退出码 1 结束,但依赖本身已装完,属于非阻塞问题,不影响启动。
3. 配置变更后如何让安装生效
现象一:改了配置但没有任何效果
pnpm install 在 lockfile 未变化时会跳过重新链接,publicHoistPattern 之类的布局配置不会被应用。
解决:
pnpm install --force
现象二:安装中断,提示需要清空 node_modules
The modules directory at "node_modules" will be removed and reinstalled from scratch.
Proceed? (Y/n)
改变 hoist 配置会要求重建整个 node_modules,而在无 TTY 的自动化环境中该确认无法响应,安装会挂起或中断。
解决:以 CI 模式跳过交互确认。
$env:CI='true'; pnpm install
4. DVA namespace 缺失
现象
控制台错误:
[ERROR] 注册数据层失败,原因:无法匹配路径'xxx'
根因
@cqsjjb/jjb-dva-runtime 会扫描 src/api/ 下的子目录,并用目录名去匹配 src/enumerate/namespace/index.js 中 defineNamespace("xxx") 声明的字符串,匹配不上则报错。
新增了 src/api/<name>/ 却没有同步添加 namespace 定义时就会触发。
解决方案
在 src/enumerate/namespace/index.js 中补充:
export const NS_XXX = defineNamespace("xxx");
本项目当前状态
src/api/ 下共 6 个目录,而 namespace 只定义了 4 个:
| 目录 | namespace | 说明 |
|---|---|---|
global |
NS_GLOBAL |
已定义 |
bi |
NS_BI |
已定义 |
driver |
NS_DRIVER |
已定义 |
register |
NS_REGISTER |
已定义 |
institution |
— | 未定义 |
supervision |
— | 未定义 |
institution 与 supervision 导出的是普通 fetch 函数,并非 DVA model 结构,当前启动日志中未出现注册报错,因此不影响运行。是否补充 namespace 属于业务设计决策:若后续要把它们改造成 DVA model,则必须同步添加定义。
约定:新增
src/api/<name>/index.js并按 DVA model 结构编写时,务必在src/enumerate/namespace/index.js中添加defineNamespace("<name>")。
5. 端口占用 EADDRINUSE
现象
Error: listen EADDRINUSE: address already in use 0.0.0.0:8080
本项目端口为 8080(见 jjb.config.js),通常是上次的开发服务器进程未正常退出。
解决方案
# 查看占用情况
netstat -ano | findstr :8080
# 只杀真正处于 LISTEN 状态的进程
Get-NetTCPConnection -LocalPort 8080 -State Listen -ErrorAction SilentlyContinue |
ForEach-Object { Stop-Process -Id $_.OwningProcess -Force }
netstat输出中的TIME_WAIT/FIN_WAIT是待回收的残留连接,不占用端口,无需处理。只有LISTENING才是真正的占用。
标准启动流程
# 1. 安装依赖(首次或配置变更后)
$env:CI='true'; pnpm install
# 2. 若提示 build scripts 被忽略
pnpm rebuild @parcel/watcher core-js es5-ext x-data-spreadsheet zy-react-library
# 3. 启动开发服务器
npm run serve:development
成功标志:
Rspack 1.7.12 compiled successfully in 22.97 s
服务地址 http://localhost:8080/。首次编译约 20-30 秒,日志停在 wait until bundle finished: / 属正常现象,需耐心等待打包完成。
检查清单
- 确认使用 pnpm,不要混用 npm 安装(会破坏
node_modules结构) - pnpm 安装类配置一律写在
pnpm-workspace.yaml,不要写进.npmrc - 用
pnpm config get <key>验证配置是否真正生效,别假设它已加载 - 改动 hoist 类配置后使用
pnpm install --force,并设$env:CI='true'跳过交互确认 - 遇到
Unable to resolve loader时,检查该 loader 是否已提升到node_modules顶层 - 新增 DVA model 目录时同步添加 namespace 定义
- 端口冲突只需关注
LISTENING状态的进程
附:已废弃的排查思路
以下做法在早期版本文档中出现过,当前项目不适用,请勿采纳:
| 废弃做法 | 说明 |
|---|---|
手动添加 history@^4.10.1 作为直接依赖 |
@cqsjjb/jjb-common-lib 自身已声明 history@^5.3.0,pnpm 会正确链接到 .pnpm store。强行加 v4 会造成版本冲突。 |
把 resolutions 迁移为 pnpm.overrides |
当前 package.json 已无 resolutions 字段,无需处理。 |
改用 npm install --legacy-peer-deps |
项目已无 package-lock.json,统一使用 pnpm。npm 的扁平化布局会与 pnpm 结构冲突。 |
在 .npmrc 中设置 shamefully-hoist / hoist / node-linker |
pnpm 11 不再从 .npmrc 读取这些配置,.npmrc 已从项目中删除。 |
处理 react-router 相关依赖问题 |
项目未依赖 react-router,src 中亦无引用。 |