在开发外部组件时如何避免“加载两个React副本”错误?

时间:2015-10-15 20:26:24

标签: reactjs npm

我正在开发一个外部组件(比方说my-component,我用npm link链接到项目(因为它正在进行中,我需要包来反映更改)。

my-component文件夹中有node_modules/reactnode_modules/react-dom,因为它们是其依赖项。但是它们是peerIpendences,所以我没想把它们带到链接这个包的项目中。

但是,当使用npm link时,它会链接整个目录,包括node_modules。因此,当项目构建时,它包括2次包:来自node_modules/*node_modules/my-component/node_modules/*

这开始影响组件何时使用ReactDOM.findDOMNode,它会导致此错误:

Warning: React can't find the root component node for data-reactid value `.0.2.0`. If you're seeing this message, it probably means that you've loaded two copies of React on the page. At this time, only a single copy of React can be loaded at a time.

此外,它可能有助于了解正在发生的事情:只有同时存在node_modules/my-component/node_modules/reactnode_modules/my-component/node_modules/react-dom时才会出现问题。如果只有其中一个,则没有错误消息。

通常的软件包安装不会带来错误,因为那里没有node_modules/react-dom

如何同时开发外部组件和项目?

8 个答案:

答案 0 :(得分:6)

通过将react-dom添加为我的webpack配置

的别名来解决此问题
alias: {

    react$: require.resolve(path.join(constants.NODE_MODULES_DIR, 'react')),
    'react-dom': require.resolve(path.join(constants.NODE_MODULES_DIR, 'react-dom'))

}

答案 1 :(得分:4)

我认为答案是在您的外部组件react中指定react-dompeerDependenciespackage.json。我尽可能遵循hereherenpm link应该(从npm@3开始)不再安装peerDependencies(或者也可以是'devDependencies)。

Aaaand我只是更仔细地阅读了你的帖子,并意识到你已经将它们指定为peerDependencies。因此,我认为答案归结为:

升级到npm@3

npm install -g npm@3.0-latest

答案 2 :(得分:3)

比我更聪明的人(@mojodna)提出了这个解决方案:从外部组件中删除重复的依赖项,并使用项目的这些deps副本解决它们。

第1步:从外部组件的node_modules

中删除依赖项

作为@cleong noted,您不能只从外部组件的node_modules中删除deps,因为当项目的外部组件中遇到现在缺少的依赖项时,它的构建步骤将失败。

第2步:将您的项目node_modules添加到NODE_PATH

要解决此问题,您可以在运行构建步骤时将项目的node_modules附加到NODE_PATH环境变量。有点像这样:

NODE_PATH=$(pwd)/node_modules/ npm start

(其中npm start是捆绑外部组件的脚本,例如Br​​owserify,Webpack等。)

实际上,您可以随时将NODE_PATH添加到您的构建脚本中,无论您是否npm link编辑任何内容,它都会有效。 (让我想知道它是否应该是默认的npm行为......)

注意:我留下了现有的答案,因为那里有一些对话,这是一个不同的(更好的)解决方案。

答案 3 :(得分:1)

问题在于npm链接。 https://github.com/npm/npm/issues/5875

npm不会将链接目录视为父项目的子项。

尝试使用npm link的替代方法:

1)在package.json

中使用相对路径依赖

2)在项目node_modules目录中手动包含依赖项

3)使用网址路径

基本上只有npm链接

答案 4 :(得分:1)

在我的webpack.config.js中添加以下内容对我有用:

resolve: {
    alias: {
        react: path.resolve(__dirname, 'node_modules', 'react')
    }
}

我还尝试了DedupePlugin(作为一种可能的补救措施here提到过),但我无法让它发挥作用。

有趣的是,当在依赖图中的多个位置找到模块时,我遇到了同一问题的不同(也许更隐蔽)的表现。

一个这样的情况是,即使我传入的类型是正确的,我的React.PropTypes.instanceOf(SomeType)约束也会发出警告。这是因为模块存在于node_modules目录树中的多个位置。由于鸭子打字,代码仍然可以工作,但我的控制台混乱了这些警告。走resolve.alias方式也使那些人沉默。

YMMV

答案 5 :(得分:0)

如果您在主项目中使用Webpack,this solution可能会有效。就我而言,project-a需要project-b。两者都需要React和ReactDOM 0.14.x

我在project-a/webpack.config.js

中有这个
resolve: {
  modulesDirectories: ['node_modules'],
  fallback: path.join(__dirname, 'node_modules')
},
resolveLoader: {
  fallback: path.join(__dirname, 'node_modules')
},
  • project-b要求peerDependencies
  • 中的React和ReactDOM为project-b/package.json
  • project-a要求project-b devDependency dependency project-a/package.json <{1}} <{1}}
  • 本地project-bproject-a相关联,如此:cd project-a; npm link ../project-b

现在,当我在npm run build内运行project-b时,更改会立即显示在project-a

答案 6 :(得分:0)

我正在使用ReactJS.net并从教程中设置webpack,并在我开始收到此错误时开始使用react-bootstrap。我发现在'react-dom': 'ReactDOM' externals的{​​{1}}列表中添加webpack.config.js修复了问题,外部列表如下所示:

  externals: {
    // Use external version of React (from CDN for client-side, or
    // bundled with ReactJS.NET for server-side)
      react: 'React',
      'react-dom': 'ReactDOM'

这似乎是google上第一个出现此错误的堆栈溢出链接,所以我认为这个答案可能对此有所帮助。

答案 7 :(得分:0)

我之所以这样,是因为我已经在我的HTML标记中添加了reactreact-dom作为外部脚本。

错误是由向组件模块添加import ReactDOM from 'react-dom'引起的。删除导入后错误消失了,模块工作正常,因为组件已经可用。