如何避免在开发时使用Webpack进行两次React加载



给定以下目录结构:

my-project
|
|-- node_modules
    |
    |-- react
    |-- module-x
        |
        |--node_modules
            |
            |--react

您可以看到我的项目模块-x都需要React。我遇到了与这个问题相同的问题,但建议从package.json依赖项中删除react。只要module-x中没有安装node_module,我就可以做到这一点,因为Webpack将使用我的项目的React。但是,如果我正在开发模块-x并安装了node_modules,则Webpack将同时使用我的项目module-x中的React。

有没有办法让Webpack确保只使用一个React实例,即使它在两个不同的级别上是必需的?

我知道我可以在开发时将模块-x保存在一个单独的目录中,但似乎我必须发布它,然后将它安装在我的项目中进行测试,这不是很有效。我考虑过npm link,但没有成功,因为它仍然在模块-x中安装了node_modules。

这听起来和我面临的挑战很像,但npm dedupe或Webpack的重复数据消除选项似乎不起作用。我可能不了解一些重要的细节。

使用npm link时通常会出现此问题。链接模块将在其自己的模块树中解析其依赖项,这与需要它的模块树不同。因此,npm link命令安装peerDependenciesdependencies

您可以使用resolve.alias强制require('react')解析为本地版本的React。

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

如果您不想(或不能)修改项目配置,有一个更简单的解决方案:只需npm link将自己反应回您的项目:

# link the component
cd my-app
npm link ../my-react-component
# link its copy of React back to the app's React
cd ../my-react-component
npm link ../my-app/node_modules/react

为了防止它对其他人有用,上面建议的解决方案对我不起作用,我必须执行以下步骤来解决它:

在库中

  1. 将生成问题的库设置为package.json中的peerDependencies,而不是dependenciesdevDependencies,例如在我的情况下为react
"peerDependencies": {
  "react": "^16.8.6",
  ...
}
  1. 运行npm install
  2. 构建库(在我的例子中,使用rollup -cnpm脚本

在我的主应用程序中

  1. 将我的库的版本更改为指向package.json中具有相对路径的本地项目,例如
"dependencies": {
  "my-library": "file:../../libraries/my-library",
  ...
}
  1. resolve.symlinks = false添加到我的主应用程序的webpack配置

  2. --preserve-symlinks-main--preserve-symlinks添加到我的package.json启动脚本中,例如:

"scripts": {
  "build": "set WEBPACK_CONFIG_FILE=all&& webpack",
  "start": "set WEBPACK_CONFIG_FILE=all&& webpack && node --preserve-symlinks-main --preserve-symlinks dist/server.js",
}
  1. 运行npm install
  2. 运行npm run start

与公认的答案一样,以下是如何使用Craco:实现所需结果

const path = require('path')
module.exports = {
  webpack: {
    configure: config => {
      config = {
        ...config,
        resolve: {
          ...config.resolve,
          alias: {
            ...config.resolve.alias,
            'react': path.resolve('./node_modules/react'),
          },
        },
      }
      // console.log(config)
      return config
    },
  },
}

需要注意的是,不能只将resolve作为密钥传递,必须使用configure回调进行自己的深度合并。

最新更新