Monorepo中不同子包依赖不同React版本导致构建失败怎么办?
在Lerna项目里有两个子包,一个用React18另一个用React17,当我运行lerna run build时老是报错说peer dependency冲突。已经试过用 resolutions强行指定版本,但构建还是失败,控制台全是红色警告:
warning "react-components@1.0.0" has incorrect peer dependency "react@^17.0.2".
warning "new-feature@2.0.0" has incorrect peer dependency "react@^18.2.0".
改成了Yarn Workspaces后虽然安装没问题,但打包时两个包的React版本还是冲突,该怎么优雅地隔离它们的依赖呢?
首先,确保你的项目已经切换到 Yarn Workspaces 或者 pnpm 的 workspace 模式,因为这些工具对 Monorepo 的支持更好。你提到已经试过 Yarn Workspaces,那就继续用它。
接下来,给每个子包设置独立的 node_modules。具体做法是在每个子包的 package.json 中添加一个字段
"installConfig": { "hoisting": false }。这个配置会告诉 Yarn 不要将这个包的依赖提升到根目录的 node_modules,从而防止不同版本的 React 被注入到同一个上下文中。如果你使用的是 pnpm,它默认就会为每个子包创建独立的 node_modules 结构,所以不需要额外配置。不过要注意,pnpm 的 symlink 机制可能会导致一些特殊的构建工具链问题,记得检查一下你的 Webpack 或 Rollup 配置是否正确处理了 pnpm 的依赖路径。
然后,重点来了,你需要确保构建工具不会错误地解析到错误版本的 React。比如,如果你用的是 Webpack,可以在每个子包的 Webpack 配置里明确指定 resolve.alias,像这样:
这一步是为了强制 Webpack 只使用当前子包下的 React 版本,而不是去根目录或者其他地方找。
另外,提醒一下,peer dependency 的警告虽然烦人,但并不一定会影响运行。如果构建成功了,只是控制台有警告,可以暂时忽略。不过从长期维护的角度来看,最好还是尽量升级所有子包到同一个 React 版本,减少技术债。
最后,还有一个更激进的方案是用工具比如
module-federation或者微前端架构,把两个子包彻底拆成独立的应用,这样它们的依赖完全隔离,但这个方案改动比较大,适合复杂场景。总之,推荐先试试独立 node_modules 加上 Webpack alias 的组合,这是成本最低、见效最快的解法。如果还有问题,可以再细聊。