前言
在 monorepo
技术成为多包管理/调试的常用方式之后,其实不应该优先考虑使用 npm link
来实现开发环境多包调试。但因为笔者所要操作的两个仓库的基建都是比较陈旧的,且考虑到未来可能会有大重构,以短期解决效率问题为主。所以还是采用通过 npm link
来解决多包管理,其中遇到了两个仓库都依赖 React
版本而导致的问题,踩了一些坑,借此记录一下,希望能帮助其他人。
npm link 作用
官方文档 docs.npmjs.com/cli/v8/comm…
我们有两个仓库 package-A
和 package-B
,其中 package-A
依赖了 package-B
,由于两个仓库都是 npm
包,所以当需要同时调试 A
和 B
时,在早之前我们只能先修改 B
的代码发布到远程,然后升级 A
中的依赖,再继续调试 A
,这样的效率是非常低下的。
有了 npm link
之后,我们可以通过其命令设置 A
仓库 node_modules
中 B
包软连到本地的 B
仓库。 这样我们修改本地 B
仓库代码时, A
仓库就可以实时编译更新,做到同时调试两个仓库。来看一下具体做法:
第一步
# 进入B仓库目录
cd package-B
# 将其本地仓库代码连接到Node根目录node_modules里
npm link
复制代码
第二步
# 进入A仓库目录
cd package-A
# 将B依赖软连到根目录node_modules上的package-b,变向指向了本地的package-B包
npm link package-b
复制代码
通过上面两张效果图,可以看到我们通过 npm link
实现了 A
仓库里的依赖 B
是本地 B
仓库的代码(目录结果一致,vscode编辑器上有软连标志)。
相同依赖版本不一致问题
仔细观察上一张图,我们可以发现 B
仓库的 node_modules
也被“移到”了 A
仓库的 node_modules
下面,这样会带来什么问题呢?根据 npm
寻找依赖的方式,它会优先寻找自身 node_modules
包里是否存在所需依赖,如果不存在,才会向上层的 node_modules
里去寻找,依次找到根目录 node_modules
。
所以当我们两个仓库同时依赖 React
时,React
不允许有多个实例出现。当启动 A
仓库dev服务,package-b
依赖了自己的版本,package-a
也依赖了自己的版本,造成了多实例,React
包会抛出异常。
具体报错信息及官方说明(第3点):reactjs.org/warnings/in…
解决
解决方法1
利用官方提供的方案,我们可以进入被依赖的仓库 package-b
,将其依赖的 React
也通过 npm link
指向 package-a
中的 React
。 这样整体 A
依赖了本地 B
,B
依赖了本地 A
的 React
版本。 有些奇怪
这种方法虽然我没有成功(可能是自己当时各种碰壁瞎试,使其没有生效),理论上是一种可行方案。
解决方法2
有文章提出(找不到链接了),如果package-b
依赖的 React
不需要编译到源代码中,也就是 React
是 peer Dependencies
依赖。可以通过移除 dev Dependencies
中的 react
,使其 install
时不安装 react
。
这种方法不适用于其他包中依赖 React
,例如 B
中依赖了 C
,C
是一个打包工具(必须需要,无法剔除),它依赖了 React
,导致一个 react
版本就会被下载下来。
注: 这种方法还有一点不好,想单独调试 B
的时候,又需要 dev Dependencies
中的 react
解决方法3
因为我们只需要运行时保持同一份 React
,所以我们可以修改 A
仓库的编译配置,使其在dev环境下,react
都指向同一份代码。这里踩了一个小坑,以为要修改 B
仓库的配置,但其实运行的服务的是 A
。当然要指定 A
的配置
// webpack 示例
module.exports = {
//...
resolve: {
alias: {
react: path.resolve(__dirname, './node_modules/react'),
'react-dom': path.resolve(__dirname, './node_modules/react-dom'),
},
},
};
复制代码
结尾
感谢阅读,希望可以帮助到你,有其他问题可以留言,或者加微信,一起探讨技术。