dwj*_*ton 6 symlink npm reactjs lerna peer-dependencies
我有一个相当标准的 lerna monorepo,它看起来像这样:
packages/
main/ - This is the main deployable application, it depends on both dep and react-dep
dep/ - Just some pure functions, no problems here
react-dep/ - A design system built with react, this is where we have problems.
Run Code Online (Sandbox Code Playgroud)
因此,发生的一个非常常见的问题是,一旦您开始在依赖库中使用钩子,就会收到以下消息:
Error: Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons:
1. You might have mismatching versions of React and the renderer (such as React DOM)
2. You might be breaking the Rules of Hooks
3. You might have more than one copy of React in the same app
See https://reactjs.org/warnings/invalid-hook-call-warning.html for tips about how to debug and fix this problem.
Run Code Online (Sandbox Code Playgroud)
这是因为您的应用程序中有两个版本的 React,一个来自主应用程序,另一个来自依赖项。
现在 - 我已经使用并有效的一个常见解决方案react是externals在您的 webpack 配置中声明和任何其他共享/对等依赖项。例如,正如这里建议的那样。或者看看这个 Github issue 从 react 线程。
但是,我不喜欢这个解决方案,首先,如果我不使用 webpack 怎么办,其次我不必手动跟踪我需要标记为外部的依赖项。
我认为应该起作用的是:
在react-dep我宣布react在这两个devDependencies和peerDependencies。我把它放进去的原因devDependencies是因为我的依赖库很可能使用 storybook 或类似的东西来开发组件,所以我确实需要在开发中做出反应。
我认为如果我发布react-dep到 npm 并使用来自 npm in 的编译代码,这应该可以工作main,因为只会dependencies被提取。
但是,我认为由于 lerna 符号链接,在这种情况下会发生 dev 依赖项仍然存在并且我们收到此错误。
有没有办法为 lerna monorepo 解决这个问题?
这是演示此问题的 github 存储库:https : //github.com/dwjohnston/lerna-react-monorepo
据我所知,这个问题可能可以使用lerna、npm或yarn来解决webpack。
我想webpack在那里提出另一种解决方案,向您的存储库打开一个公关。如果某个webpack解决方案不适合您,请忽略此答案。
它比externals机制好一点,因为它会自动跟踪重叠的对等依赖关系。
module.exports = function(config) {
config.plugins.push(
new NormalModuleReplacementPlugin(re, function(resource) {
// first, remove babel and other loaders paths
const requestWithoutLoaderMeta = resource.request.split('!');
const requestPath = requestWithoutLoaderMeta.length && requestWithoutLoaderMeta[requestWithoutLoaderMeta.length - 1];
if (requestPath) {
// looking for a dependency and package names
const packagesPath = resolve(__dirname, '../') + '/';
const requestPathRel = requestPath.replace(packagesPath, '');
const [packageName, _, depName] = requestPathRel.split('/');
// if the main package has this dependency already - just use it
if (dependencies[packageName]) {
console.log('\x1b[35m%s\x1b[0m', `[REPLACEMENT]: using dependency <${depName}> from package [main] instead of [${packageName}]`);
resource.request = resource.request.replace(`${packageName}/node_modules/${depName}`, `main/node_modules/${depName}`)
}
}
})
);
return config;
}
Run Code Online (Sandbox Code Playgroud)
此代码将main使用 解决包中的对等依赖关系webpack.NormalModuleReplacementPlugin。
关于 webpack 的注意事项:由于所有三个前端之王都在他们的 CLI(Angular、React、Vue)中使用它,我认为您可以轻松、安全地使用它来进行此类自定义。
我很高兴听到替代技术(例如纱线)来解决这个问题。
为您的下一个 monorepo 尝试一下@nrwl/nx而不是lerna.
主要区别在于nrwl项目通常只有一个package.json(使用 Google 经验),因此您需要为所有包安装一次依赖项,并且不会遇到您所描述的问题。
| 归档时间: |
|
| 查看次数: |
1009 次 |
| 最近记录: |