Turbo monorepo+pnpm多React版本共存:阻止根目录版本提升
问题描述
在Turbo monorepo环境下使用pnpm时,遇到React版本冲突问题:
apps/web依赖 React 16,apps/widget依赖 React 18- 两个版本的React均被pnpm提升至根目录
node_modules中,导致依赖React 16的web项目错误加载React 18,触发报错:
TypeError: Cannot read properties of null (reading 'useRef') at Object.useRef (/Users/joe-doe/customer/node_modules/.pnpm/react@18.2.0/node_modules/react/cjs/react.development.js:1630:21)
项目目录结构:
. └── customer ├── apps/ │ ├── web │ │ └── package.json <-- 依赖React 16 │ └── widget │ └── package.json <-- 依赖React 18 ├── package.json <-- 仅包含TS、eslint等公共依赖 └── node_modules └── .pnpm ├── ... 其他依赖 ├── react@16.14.0 └── react@18.2.0
当前.npmrc配置:
strict-peer-dependencies=false auto-install-peers=false resolution-mode=highest public-hoist-pattern[]=*eslint* public-hoist-pattern[]=*prettier* public-hoist-pattern[]=@types*
已尝试的无效配置:
hoist-pattern[]=!react@18.2.0 hoist-pattern[]=!react hoist-pattern[]=!*react* public-hoist-pattern[]=!react@18.2.0 public-hoist-pattern[]=!react public-hoist-pattern[]=!*react*
解决方案
1. 修正.npmrc配置,彻底排除React的hoist
将以下配置添加到根目录.npmrc中,禁止所有React相关包被提升到根node_modules:
# 禁止React及ReactDOM被提升 hoist-pattern[]=!*react* hoist-pattern[]=!*react-dom* public-hoist-pattern[]=!*react* public-hoist-pattern[]=!*react-dom*
2. 移除resolution-mode=highest配置
该配置会让pnpm优先选择依赖的最高版本,可能导致子项目指定的低版本React被强制升级。删除后,pnpm会严格遵循子项目package.json中指定的版本。
3. 锁定子项目的React精确版本
在apps/web/package.json中明确指定React 16的精确版本:
{ "dependencies": { "react": "16.14.0", "react-dom": "16.14.0" } }
在apps/widget/package.json中明确指定React 18的精确版本:
{ "dependencies": { "react": "18.2.0", "react-dom": "18.2.0" } }
4. 清理缓存并重新安装依赖
执行以下命令彻底清理缓存、删除现有依赖后重新安装:
pnpm store prune rm -rf node_modules rm -rf apps/web/node_modules rm -rf apps/widget/node_modules pnpm install
5. 验证依赖解析
通过以下命令检查子项目的React版本是否符合预期:
# 检查web项目的React版本 pnpm --filter web list react # 检查widget项目的React版本 pnpm --filter widget list react
完成以上步骤后,两个子项目将各自加载对应版本的React,版本冲突问题即可解决。
内容的提问来源于stack exchange,提问作者Pan Vi
相关产品推荐
相关产品推荐

