# 依赖问题排查指南 本文档记录本项目在依赖安装与启动过程中的实际问题、根因与解决方案。 ## 项目环境基线 | 项 | 值 | | --- | --- | | 包管理器 | **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 未被提升 这是本项目实际遇到的**唯一阻塞启动**的错误。 ### 现象 ```text 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 已不读取该文件。可用以下命令验证配置是否真正生效: ```powershell pnpm config get public-hoist-pattern # 失效时返回 undefined ``` ### 解决方案 在 `pnpm-workspace.yaml` 中声明 `publicHoistPattern`: ```yaml publicHoistPattern: - '*loader*' - '*webpack-plugin*' - 'react-refresh' - '@babel/*' - 'postcss' - 'autoprefixer' ``` 注意通配符要写成 `*loader*` 而非 `*loader`,确保能匹配 `babel-loader`、`css-loader` 等带连字符的包名。 修改后必须重新安装才能生效(见下方「配置变更后如何让安装生效」)。 ### 验证 ```powershell @('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 被忽略 ### 现象 ```text [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` 块: ```yaml onlyBuiltDependencies: - '@parcel/watcher' - core-js - es5-ext - x-data-spreadsheet - zy-react-library ``` 若安装后警告仍然出现,显式执行一次重建即可: ```powershell pnpm rebuild @parcel/watcher core-js es5-ext x-data-spreadsheet zy-react-library ``` > 该报错会让 `pnpm install` 以退出码 1 结束,但依赖本身已装完,属于**非阻塞**问题,不影响启动。 --- ## 3. 配置变更后如何让安装生效 ### 现象一:改了配置但没有任何效果 `pnpm install` 在 lockfile 未变化时会跳过重新链接,`publicHoistPattern` 之类的布局配置不会被应用。 **解决**: ```powershell pnpm install --force ``` ### 现象二:安装中断,提示需要清空 `node_modules` ```text The modules directory at "node_modules" will be removed and reinstalled from scratch. Proceed? (Y/n) ``` 改变 hoist 配置会要求重建整个 `node_modules`,而在无 TTY 的自动化环境中该确认无法响应,安装会挂起或中断。 **解决**:以 CI 模式跳过交互确认。 ```powershell $env:CI='true'; pnpm install ``` --- ## 4. DVA namespace 缺失 ### 现象 控制台错误: ```text [ERROR] 注册数据层失败,原因:无法匹配路径'xxx' ``` ### 根因 `@cqsjjb/jjb-dva-runtime` 会扫描 `src/api/` 下的子目录,并用目录名去匹配 `src/enumerate/namespace/index.js` 中 `defineNamespace("xxx")` 声明的字符串,匹配不上则报错。 新增了 `src/api//` 却没有同步添加 namespace 定义时就会触发。 ### 解决方案 在 `src/enumerate/namespace/index.js` 中补充: ```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//index.js` 并按 DVA model 结构编写时,务必在 `src/enumerate/namespace/index.js` 中添加 `defineNamespace("")`。 --- ## 5. 端口占用 `EADDRINUSE` ### 现象 ```text Error: listen EADDRINUSE: address already in use 0.0.0.0:8080 ``` 本项目端口为 **8080**(见 `jjb.config.js`),通常是上次的开发服务器进程未正常退出。 ### 解决方案 ```powershell # 查看占用情况 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` 才是真正的占用。 --- ## 标准启动流程 ```powershell # 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 ``` 成功标志: ```text Rspack 1.7.12 compiled successfully in 22.97 s ``` 服务地址 。首次编译约 20-30 秒,日志停在 `wait until bundle finished: /` 属正常现象,需耐心等待打包完成。 --- ## 检查清单 - [ ] 确认使用 **pnpm**,不要混用 npm 安装(会破坏 `node_modules` 结构) - [ ] pnpm 安装类配置一律写在 `pnpm-workspace.yaml`,**不要**写进 `.npmrc` - [ ] 用 `pnpm config get ` 验证配置是否真正生效,别假设它已加载 - [ ] 改动 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` 中亦无引用。 |