有没有办法让lernanpm "真正在我自己的node_modules中查找那些同行的依赖关系"?

问题描述 投票:2回答:1

我有一个相当标准的 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. 

一个很常见的问题是,一旦你开始在依赖库中使用钩子,你就会收到这个消息。

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.

这是因为在你的应用程序中有两个版本的React 一个来自主应用程序,一个来自依赖库。

现在--一个常见的解决方案,我已经用过了,并且是有效的,就是声明一下 react 和任何其他共享同行的依赖关系,如 externals 在你的webpack配置中。比如,这里建议的。 或者看看 这个Github问题线程来自react.

然而,我并不喜欢这种解决方案,首先,如果我没有使用webpack怎么办,其次,我不应该手动跟踪哪些依赖关系需要标记为外部。

我认为应该这样做。

在... react-dep 我宣布 react 在两个 devDependenciespeerDependencies. 我之所以把它放进去 devDependencies 是因为我的依赖库很可能使用storybook或类似的方式来开发组件,所以我确实需要在开发中做出反应。

我想,如果我在发布的是 react-dep 到npm,并在npm中消耗编译后的代码。main因为只有 dependencies 将会被获取。

然而,我认为由于 lerna symlinking 的原因,在这种情况下会发生的情况是 dev 依赖仍然存在,我们会得到这个错误。

有什么方法可以解决这个问题吗?

这里的github repo演示了这个问题。https:/github.comdwjohnstonlerna-react-monorepo。

reactjs npm symlink lerna peer-dependencies
1个回答
1
投票

在我看来,这个问题可能可以通过以下方法来解决 lerna, npm, yarnwebpack. 我想再提一个建议 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;
}

这段代码将解决你的对等依赖关系,从 main 包,使用 webpack.NormalModuleReplacementPlugin.

关于webpack的说明:因为三个前端之王都在他们的CLI中使用它(angular,react,vue),我认为你可以轻松安全地使用它来进行这样的定制。

我很乐意听到关于解决这个问题的替代技术(比如yarn)。

@nrwlnx 试试你的下一个单兵作战,以代替 lerna. 主要区别在于 nrwl 项目通常有一个 package.json 仅仅是(使用Google经验),所以你需要为所有的包安装一次依赖关系,而不会面临你描述的问题。

© www.soinside.com 2019 - 2024. All rights reserved.