npm link 踩坑记

框架说明

项目采用 react 库进行开发

坑的出现

目前项目 A 开发中过程中有一些比较通用的大组件,比较合适单独提取出来作为一个项目 B,然后在

  • 开发阶段
    使用 npm link 的方式将 B 组件软链接到 A 项目中

  • 生产阶段
    使用 npm i B -S 的方式将 B 组件作为 A 项目的 dependencies

A、B 都依赖于 react , 在开发阶段通过 npm link B 的方式 B 映入到 A 中时问题出现了

Uncaught Invariant Violation: addComponentAsRefTo(…): Only a ReactOwner can have refs. You might be adding a ref to a component that was not created inside a component’s render method, or you have multiple copies of React loaded (details: fb.me/react-refs-must-have-owner).

查找问题

然后我就顺藤摸瓜到了 https://reactjs.org/warnings/refs-must-have-owner.html, 官方给出了三种可能

  • You are trying to add a ref to a functional component
  • You are trying to add a ref to an element that is being created outside of a component’s render() function
  • You have multiple (conflicting) copies of React loaded (eg. due to a misconfigured npm dependency)

    第一种情况说可能是我在函数式组件里面使用到了 ref 属性,检查代码后发现并没有,所以这种原因可以排除;

    第二种情况可能是我在 render 方法外定义的组件中使用到了 ref, 经过检查也没有,所以也排除了这个原因;

    只剩下最后一种情况了,npm 中同时存在 2 个 react ,问题终于找到了

    尝试解决

  1. 首先想到的是:会不会是因为用的其他 React 第三方库作者在开发组件库的时候将 react 写进了 dependenices 中,导致 npm 在安装的时候安装了 2 次,然后排查了下项目依赖的第三方库中比较可疑的,还真发现了一个,然后找作者解决了这个问题,然后再试了下,遗憾的是并没有解决到问题;

  2. 然后在想可能还有些没有排查干净,于是新建了一个无任何其他第三方的 demo 项目进行测试,发现还是有这个问题,说明问题应该不是因为将 react 放在了 dependencies,而没有放在 peerDependencies 中造成的.

  3. 然后尝试将 B 组件编译打包发布到 npm 仓库中去,然后像上面提到的生产环境使用的方式去使用,神奇了,居然不报上麦的错误了,程序能正常 run 起来了,这不正好说明是 是使用 npm link 的锅么?

    解决方法

既然确定了问题所在,那就带着问题去 Google 上搜索 npm link react , 第一条结果就有描述, 原来是因为通过 npm link 的方式添加进来的组件,这些组件中使用到的 react 会在源地址中去查找 react, 然后本身 A 项目已经包含了一个版本的 react,所以就会提示包含了 2 个版本的 react, 解决方案可以在 webpack config 文件中配置 alias, 将 react 手动指向 A 项目中的 node_moudules/react, 如下:

1
2
3
4
5
6
7
8
9
module.exports = {
...
resolve: {
alias: {
react: path.resolve('./node_modules/react'),
}
}
...
}

这样就能确保只会在一个地方去找 React 了。

【完】

参考: