176

我正在尝试做一些我认为应该是可能的事情,但我真的无法从 webpack 文档中理解如何去做。

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

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

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

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

  • 一个(需要: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 插件只会在需要时扩展 $ 全局(如果它们可用于其他不需要它们的模块,这不是问题)。

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

4

4 回答 4

140

在我的 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
]

现在我有一个文件,它只根据需要将第 3 方库添加到一个文件中。

如果您想在分隔供应商和入口点文件的位置更细化:

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 用户的 indexOf 搜索更改

于 2016-08-03T03:26:18.697 回答
55

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

供应商捆绑包。

您应该为此使用CommonsChunkPlugin。在配置中,您指定块的名称(例如vendor),以及将生成的文件名(vendor.js)。

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

现在很重要的部分,您现在必须指定库的含义vendor,然后在入口部分执行此操作。与新声明的块的名称相同的条目列表中再添加一项(即在这种情况下为“供应商”)。该条目的值应该是您要移动到vendor捆绑的所有模块的列表。在您的情况下,它应该类似于:

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

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

于 2015-05-20T09:57:17.083 回答
44

如果您有兴趣将脚本与供应商的脚本分开自动捆绑:

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'})
  ]
};

您可以在官方文档中阅读有关此功能的更多信息。

于 2016-04-19T08:03:08.870 回答
13

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

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

于 2015-05-23T23:02:42.707 回答