safety-eval-website/docs/dependency-issues-guide.md

8.3 KiB
Raw Blame History

依赖问题排查指南

本文档记录本项目在依赖安装与启动过程中的实际问题、根因与解决方案。

项目环境基线

包管理器 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-patternhoistnode-linker 等安装配置,这些配置已迁移到 pnpm-workspace.yaml,并改用小驼峰命名(publicHoistPatternnodeLinker)。项目原有的 .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 默认采用隔离式isolatednode_modules 布局,传递依赖只存在于 node_modules/.pnpm/ 虚拟存储中不会出现在顶层。Rspack 解析 loader 时按名称在顶层查找,因而失败。

项目原本试图用 .npmrcpublic-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-loadercss-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.jsdefineNamespace("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 未定义

institutionsupervision 导出的是普通 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.0pnpm 会正确链接到 .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-routersrc 中亦无引用。