如何单独捆绑供应商脚本并根据需要使用 Webpack?

我正在尝试做一些我认为应该是可能的事情,但我真的不能理解如何仅仅从 webpack 文档做到这一点。

我正在编写一个包含几个模块的 JavaScript 库,这些模块可能相互依赖,也可能不相互依赖。除此之外,所有模块都使用 jQuery,其中一些可能需要 jQuery 插件。这个库将用于几个不同的网站,可能需要一些或所有的模块。

定义模块之间的依赖关系非常容易,但是定义它们的第三方依赖关系似乎比我预期的要难。

我想实现的目标 : 对于每个应用程序,我希望有两个捆绑文件,一个具有必要的第三方依赖关系,另一个具有我库中必要的模块。

例子 : 让我们假设我的库有以下模块:

  • A (需要: jquery,jquery.plugin1)
  • B (需要: jquery,a)
  • C (需要: jquery,jquery.ui,a,b)
  • D (需要: jquery,jquery.plugin2,a)

我有一个应用程序(见它作为一个唯一的条目文件) ,需要模块 a,b 和 c Webpack 为这种情况应该生成以下文件:

  • 厂商包 : 包含 jquery、 jquery.plugin1和 jquery.ui;
  • 网站资料套 : 附有模组 a、 b 及 c;

最后,我希望 jQuery 是一个全局的,这样我就不需要在每个文件上都需要它(例如,我可以只在主文件上需要它)。而 jQuery 插件只是在需要的情况下扩展 $global (如果它们可用于其他不需要它们的模块,那就没有问题)。

假设这是可能的,那么在这种情况下,webpack 配置文件的例子是什么呢?我在我的配置文件中尝试了几种加载器、外部组件和插件的组合,但是我并不真正了解它们在做什么,以及我应该使用哪些组合。谢谢!

120313 次浏览

我不确定我是否完全理解你的问题,但是因为我最近有类似的问题,我会尽力帮助你。

供应商捆绑。

你应该使用 Commons ChunkPlugin。在配置中,指定块的名称(例如 vendor)和将要生成的文件名(vendor.js)。

new webpack.optimize.CommonsChunkPlugin("vendor", "vendor.js", Infinity),

现在是重要的部分,您现在必须指定什么是 vendor库,并在条目部分进行指定。再向条目列表添加一个与新声明的块名称相同的项(例如,在本例中为“供应商”)。该条目的值应该是要移动到 vendor包的所有模块的列表。 在你的情况下,它应该是这样的:

entry: {
app: 'entry.js',
vendor: ['jquery', 'jquery.plugin1']
}

作为全局的 JQuery

遇到同样的问题,用 提供插件解决了。这里你没有定义全局对象,而是定义了模块的快捷方式。也就是说,你可以这样配置它:

new webpack.ProvidePlugin({
$: "jquery"
})

现在你可以在代码的任何地方使用 $-webpack 会自动将其转换为

require('jquery')

我希望它有帮助。你也可以看看我的网络包配置文件是 给你

我喜欢 webpack,但是我同意这个文档不是世界上最好的... 但是嘿。.人们一开始也是这么说 Angular 文档的:)


编辑:

要获得特定于入口点的供应商块,只需多次使用 CommonsChunkPlugins:

new webpack.optimize.CommonsChunkPlugin("vendor-page1", "vendor-page1.js", Infinity),
new webpack.optimize.CommonsChunkPlugin("vendor-page2", "vendor-page2.js", Infinity),

然后为不同的文件声明不同的扩展库:

entry: {
page1: ['entry.js'],
page2: ['entry2.js'],
"vendor-page1": [
'lodash'
],
"vendor-page2": [
'jquery'
]
},

如果一些库在入口点之间是重叠的(并且大部分是重叠的) ,那么您可以使用不同配置的相同插件将它们提取到公共文件中。参见 这个示例。

也不确定我是否完全理解您的情况,但这里有一个配置片段,可以为您的每个捆绑包创建单独的供应商块:

entry: {
bundle1: './build/bundles/bundle1.js',
bundle2: './build/bundles/bundle2.js',
'vendor-bundle1': [
'react',
'react-router'
],
'vendor-bundle2': [
'react',
'react-router',
'flummox',
'immutable'
]
},


plugins: [
new webpack.optimize.CommonsChunkPlugin({
name: 'vendor-bundle1',
chunks: ['bundle1'],
filename: 'vendor-bundle1.js',
minChunks: Infinity
}),
new webpack.optimize.CommonsChunkPlugin({
name: 'vendor-bundle2',
chunks: ['bundle2'],
filename: 'vendor-bundle2-whatever.js',
minChunks: Infinity
}),
]

链接到 CommonsChunkPlugin文档: http://webpack.github.io/docs/list-of-plugins.html#commonschunkplugin

如果您有兴趣自动捆绑您的脚本从供应商的:

var webpack = require('webpack'),
pkg     = require('./package.json'),  //loads npm config file
html    = require('html-webpack-plugin');


module.exports = {
context : __dirname + '/app',
entry   : {
app     : __dirname + '/app/index.js',
vendor  : Object.keys(pkg.dependencies) //get npm vendors deps from config
},
output  : {
path      : __dirname + '/dist',
filename  : 'app.min-[hash:6].js'
},
plugins: [
//Finally add this line to bundle the vendor code separately
new webpack.optimize.CommonsChunkPlugin('vendor', 'vendor.min-[hash:6].js'),
new html({template : __dirname + '/app/index.html'})
]
};

您可以在 正式文件中了解更多关于这个特性的信息。

在我的 webpack.config.js (版本1,2,3)文件中,我有

function isExternal(module) {
var context = module.context;


if (typeof context !== 'string') {
return false;
}


return context.indexOf('node_modules') !== -1;
}

在我的插件数组中

plugins: [
new CommonsChunkPlugin({
name: 'vendors',
minChunks: function(module) {
return isExternal(module);
}
}),
// Other plugins
]

现在我有一个文件,只添加第三方库到一个文件所需要的。

如果您希望在分离供应商和入口点文件时获得更细粒度的信息:

plugins: [
new CommonsChunkPlugin({
name: 'common',
minChunks: function(module, count) {
return !isExternal(module) && count >= 2; // adjustable
}
}),
new CommonsChunkPlugin({
name: 'vendors',
chunks: ['common'],
// or if you have an key value object for your entries
// chunks: Object.keys(entry).concat('common')
minChunks: function(module) {
return isExternal(module);
}
})
]

请注意,插件的顺序非常重要。

此外,这将改变版本4。当这是正式的,我更新这个答案。

更新: 对 windows 用户的索引搜索更改