我正在开发一个外部组件(假设是my-component
,我将其与npm link
链接到项目(因为它正在进行中,我需要包来反映更改)。
在my-component
文件夹中有node_modules/react
和node_modules/react-dom
,因为它们是它的依赖项。然而,它们是peerdependencies,所以我不打算把它们带到链接这个包的项目中。
然而,当使用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/react
和node_modules/my-component/node_modules/react-dom
都存在时才会出现问题。如果只有其中一个,则没有错误消息。
通常的软件包安装不会出现这样的错误,因为那里没有node_modules/react-dom
。
如何同时开发外部组件和项目?
问题是双重的:
- 你不能有两个副本的react加载
- npm link创建了一个符号链接,但是require不尊重当它尝试在目录上导航时,它永远不会查找父项目的反应。
解决方案:
你所要做的就是把你组件中的react和react-dom链接到父项目的node_modules文件夹。
找到你的组件项目,删除react和react-dom,然后执行
npm link ../myproject/node_modules/react
npm link ../myproject/node_modules/react-dom
将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'))
}
比我更聪明的人(@mojodna)提出了这个解决方案:从外部组件中删除重复的依赖项,并使用项目中这些依赖项的副本来解决它们。
步骤1:从外部组件的node_modules
正如@cleong所指出的,你不能仅仅从外部组件的node_modules
中删除深度,因为当你的项目的构建步骤遇到外部组件中现在缺失的依赖项时,它将失败。
步骤2:将项目的node_modules
添加到NODE_PATH
要解决这个问题,您可以在运行构建步骤时将项目的node_modules
附加到NODE_PATH
环境变量。例如:
NODE_PATH=$(pwd)/node_modules/ npm start
(其中npm start
是绑定外部组件的脚本,例如Browserify, Webpack等)
事实上,你总是可以把NODE_PATH
添加到你的构建脚本中,不管你是否添加了npm link
,它都会起作用。(让我怀疑它是否应该是默认的npm
行为…)
注:我留下了我现有的答案,因为那里有一些对话,这是一个不同的(更好的)解决方案。
我认为答案是在外部组件的package.json
中将react
和react-dom
指定为peerDependencies
。尽我所能遵循这里和这里,npm link
应该(作为npm@3
)不再安装peerDependencies
(或' devDependencies要么)。
aaa,我只是更仔细地阅读了你的帖子,意识到你已经将它们指定为peerDependencies
。因此,我认为答案可以归结为:
升级到npm@3
:
npm install -g npm@3.0-latest
问题是npm链接。https://github.com/npm/npm/issues/5875
npm不把链接的目录当作父项目的子项目。
尝试npm的替代方法link:
在package.json 中使用相对路径依赖2)在你的项目node_modules目录中手动包含你的依赖项 3)使用url路径基本上任何东西,但npm链接
在我的webpack.config.js
中添加以下内容:
resolve: {
alias: {
react: path.resolve(__dirname, 'node_modules', 'react')
}
}
我也尝试了DedupePlugin
(这里提到的可能的补救措施),但我不能让它工作。
同样有趣的是,当一个模块出现在依赖关系图的多个位置时,我遇到了相同问题的不同表现(可能更阴险)。
这样的一个例子是,即使我传入的类型是正确的,我的React.PropTypes.instanceOf(SomeType)
约束也会发出警告。这是由于模块出现在node_modules
目录树中的多个位置。由于使用duck-typing,代码仍然可以工作,但我的控制台被这些警告弄得乱七八糟。用resolve.alias
的方式也让这些人沉默了。
YMMV
我正在使用ReactJS.net和设置webpack从那里的教程,并开始使用react-bootstrap
以及当我开始得到这个错误。我发现将'react-dom': 'ReactDOM'
添加到webpack.config.js
中的externals
列表中修复了这个问题,外部列表看起来像这样:
externals: {
// Use external version of React (from CDN for client-side, or
// bundled with ReactJS.NET for server-side)
react: 'React',
'react-dom': 'ReactDOM'
这似乎是第一个堆栈溢出链接在谷歌这个错误,所以我认为这个答案可能会帮助这里的人。
强烈建议使用https://github.com/mweststrate/relative-deps。
从本地签出安装依赖项,并保持它们同步,不受链接的限制。
这个解决了这个问题,因为它像npm install一样安装本地库,满足任何依赖版本,等等。
如果你在主项目中使用Webpack,这个解决方案可能有效。在我的例子中,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
需要React和ReactDOM作为project-b/package.json
中的peerDependencies
-
project-a
需要project-b
作为devDependency
(也应该作为dependency
工作)在project-a/package.json
cd project-a; npm link ../project-b
本地project-b
链接到project-a
如下:现在当我在project-b
内运行npm run build
时,变化立即出现在project-a
我得到这个,因为我已经将react
和react-dom
作为外部脚本包含在我的HTML标记中。
该错误是由添加import ReactDOM from 'react-dom'
到组件模块引起的。一旦我删除了导入,错误就消失了,并且模块工作正常,因为组件已经可用。