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

我试图做一些我认为应该是可能的事情,但我真的无法从webpack文档中理解如何做到这一点。

我正在编写一个JavaScript库,其中包含几个模块,这些模块可能相互依赖,也可能不相互依赖。最重要的是,所有模块都使用jQuery,其中一些模块可能需要jQuery插件。然后,该库将在几个不同的网站上使用,这些网站可能需要部分或全部模块。

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

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

示例:假设我的库具有以下模块:

  • a (require: jquery, jquery.plugin1)
  • b (要求: jquery, a)
  • c (require: jquery, jquery.ui, a, b)
  • d (require: jquery, jquery.plugin2, a)

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

  • vendor bundle: with jquery, jquery.plugin1 and jquery.ui;
  • 网站捆绑包:模块a,b和c;

最后,我更喜欢将jQuery作为全局,这样我就不需要在每个文件上都要求它(例如,我只能在主文件上要求它)。jQuery插件只会在需要它们的情况下扩展$ global(如果它们可用于其他不需要它们的模块,这不是问题)。

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


答案 1

在我的 webpack.config.js (Version 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中更改。当这是官方的,我会更新这个答案。

更新:索引窗口用户的搜索更改


答案 2

我不确定我是否完全理解您的问题,但由于我最近遇到了类似的问题,我将尽力帮助您。

供应商捆绑包。

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

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

现在重要的部分,您现在必须指定库的含义,并在条目部分中执行此操作。另一个项目要输入列表,其名称与新声明的块的名称相同(即本例中的“供应商”)。该条目的值应该是要移动到捆绑包的所有模块的列表。在你的情况下,它应该看起来像这样:vendorvendor

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

JQuery 作为全局

有同样的问题,并用ProvidEplugin解决了它。在这里,您不是在定义全局对象,而是在定义模块。即,您可以像这样配置它:

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

现在,您可以在代码中的任何位置使用 - webpack会自动将其转换为$

require('jquery')

我希望它有所帮助。你也可以看看我的 webpack 配置文件,它在这里

我喜欢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'
    ]
},

如果一些库在入口点之间重叠(并且对于大多数库),那么您可以使用相同的插件将它们提取到公共文件中,只是配置不同。请参阅此示例