webpack、rollup 等模块打包器如何处理相同依赖项的两个不同版本?
How module bundlers like webpack, rollup, handle two different versions of same dependency?
如果,module1依赖button-component@1.0.2
module2依赖button-component@1.5.0
最终包中加载了哪个版本的按钮组件?
我们可以采取哪些步骤来避免最终构建中的重复模块?
TL;DR: It is not the bundler. It is Mostly the package manager (NPM, etc.) that is responsible for providing dependencies which bundlers simply follow.
在这里工作的并不是真正的捆绑器本身。对于第三方依赖项,我们通常使用 NPM,因此通常 node_modules
。
现在 NPM 的工作是使依赖树尽可能平坦。想象下图,其中 your-code
取决于 module1
和 module2
。而且,module1
本身在内部依赖于 module2
.
your-code <-- module1@1.0.0 <--- module2@1.0.5
<-- module2@1.0.5
如果 your-code
和 module1
使用相同的依赖关系,那么 npm
会将其平放在顶级 node_modules
文件夹下,因此捆绑器 (Webpack/Rollup) 会选择单版的module
现在想象另一种情况:
your-code <-- module1@1.0.0 <--- module2@1.0.5
<-- module2@2.0.0
此处 your-code
使用的是 module2
的 2.0.0 版本,而 module1
使用的是不同的版本。这是一个突破性的变化。在这种情况下,npm 不会保持平整并在您的 node_modules
文件夹中安装 module2@2.0.0
,而 module2@1.0.5
将安装在 module1
的 node_modules
文件夹中。 Bundler 在打包代码时会选择这两个版本。
但这不是那个脚本的全部。通常如果依赖关系仅在 patch
版本不同,即 semver 的最后一位,那么 npm
将只选择一个而忽略另一个。此外,这种依赖关系的解决还取决于 NPM 版本控制模型。您可以使用 ^1.0.5
或 ~1.0.5
指定宽松的依赖版本。这也会影响 if NPM will install modules separately or keep it flat.
您可以使用 bundler analyzer 或等价物来检测重复依赖项。当 NPM 首次发布时,它无法处理这个问题,因此 Bower 应运而生,以帮助具有扁平依赖项的开发人员,以便打包程序只选择一个版本的依赖项。但最新的 NPM 对于大多数情况来说已经足够好了,不再使用 bower。
最后我说主要是因为一般都是包管理器。但是,在 bare 导入的情况下,您可以 teach/override 捆绑器专门从一个且仅一个版本解析。例如,考虑下面的 Webpack 解析配置:
resolve: {
// see below for an explanation
alias: {
preact: path.resolve('node_modules', 'preact')
}
}
因此,如果您不小心在依赖关系图中多次 preact
,那么您可以强制 Webpack 始终使用从一个特定文件夹导入的特定 preact
。
如果,module1依赖button-component@1.0.2
module2依赖button-component@1.5.0
最终包中加载了哪个版本的按钮组件?
我们可以采取哪些步骤来避免最终构建中的重复模块?
TL;DR: It is not the bundler. It is Mostly the package manager (NPM, etc.) that is responsible for providing dependencies which bundlers simply follow.
在这里工作的并不是真正的捆绑器本身。对于第三方依赖项,我们通常使用 NPM,因此通常 node_modules
。
现在 NPM 的工作是使依赖树尽可能平坦。想象下图,其中 your-code
取决于 module1
和 module2
。而且,module1
本身在内部依赖于 module2
.
your-code <-- module1@1.0.0 <--- module2@1.0.5
<-- module2@1.0.5
如果 your-code
和 module1
使用相同的依赖关系,那么 npm
会将其平放在顶级 node_modules
文件夹下,因此捆绑器 (Webpack/Rollup) 会选择单版的module
现在想象另一种情况:
your-code <-- module1@1.0.0 <--- module2@1.0.5
<-- module2@2.0.0
此处 your-code
使用的是 module2
的 2.0.0 版本,而 module1
使用的是不同的版本。这是一个突破性的变化。在这种情况下,npm 不会保持平整并在您的 node_modules
文件夹中安装 module2@2.0.0
,而 module2@1.0.5
将安装在 module1
的 node_modules
文件夹中。 Bundler 在打包代码时会选择这两个版本。
但这不是那个脚本的全部。通常如果依赖关系仅在 patch
版本不同,即 semver 的最后一位,那么 npm
将只选择一个而忽略另一个。此外,这种依赖关系的解决还取决于 NPM 版本控制模型。您可以使用 ^1.0.5
或 ~1.0.5
指定宽松的依赖版本。这也会影响 if NPM will install modules separately or keep it flat.
您可以使用 bundler analyzer 或等价物来检测重复依赖项。当 NPM 首次发布时,它无法处理这个问题,因此 Bower 应运而生,以帮助具有扁平依赖项的开发人员,以便打包程序只选择一个版本的依赖项。但最新的 NPM 对于大多数情况来说已经足够好了,不再使用 bower。
最后我说主要是因为一般都是包管理器。但是,在 bare 导入的情况下,您可以 teach/override 捆绑器专门从一个且仅一个版本解析。例如,考虑下面的 Webpack 解析配置:
resolve: {
// see below for an explanation
alias: {
preact: path.resolve('node_modules', 'preact')
}
}
因此,如果您不小心在依赖关系图中多次 preact
,那么您可以强制 Webpack 始终使用从一个特定文件夹导入的特定 preact
。