简体   繁体   English

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

[英]How to bundle vendor scripts separately and require them as needed with Webpack?

I'm trying to do something that I believe should be possible, but I really can't understand how to do it just from the webpack documentation. 我正在尝试做一些我认为应该可行的事情,但我真的无法理解如何从webpack文档中做到这一点。

I am writing a JavaScript library with several modules that may or not depend on each other. 我正在编写一个包含多个模块的JavaScript库,这些模块可能相互依赖或不相互依赖。 On top of that, jQuery is used by all modules and some of them may need jQuery plugins. 最重要的是,jQuery被所有模块使用,其中一些可能需要jQuery插件。 This library will then be used on several different websites which may require some or all modules. 然后,该库将用于几个可能需要部分或全部模块的不同网站。

Defining the dependencies between my modules was very easy, but defining their third-party dependencies seems to be harder then I expected. 定义我的模块之间的依赖关系非常简单,但定义他们的第三方依赖关系似乎比我预期的更难。

What I would like to achieve : for each app I want to have two bundle files one with the necessary third-party dependencies and other with the necessary modules from my library. 我想要实现的目标 :对于每个应用程序,我希望有两个捆绑文件,一个包含必要的第三方依赖项,另一个包含我库中的必要模块。

Example : Let's imagine that my library has the following modules: 示例 :假设我的库具有以下模块:

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

And I have an app (see it as a unique entry file) that requires modules a, b and c. 我有一个应用程序(将其视为唯一的条目文件),需要模块a,b和c。 Webpack for this case should generate the following files: 此案例的Webpack应生成以下文件:

  • vendor bundle : with jquery, jquery.plugin1 and jquery.ui; 供应商包 :使用jquery,jquery.plugin1和jquery.ui;
  • website bundle : with modules a, b and c; 网站包 :模块a,b和c;

In the end, I would prefer to have jQuery as a global so I don't need to require it on every single file (I could require it only on the main file, for example). 最后,我更喜欢将jQuery作为全局文件,因此我不需要在每个文件上都需要它(例如,我只需要在主文件上使用它)。 And jQuery plugins would just extend the $ global in case they are required (it is not a problem if they are available to other modules that don't need them). 并且jQuery插件只是在需要时扩展$ global(如果它们可用于不需要它们的其他模块则不是问题)。

Assuming this is possible, what would be an example of a webpack configuration file for this case? 假设这是可能的,那么这个案例的webpack配置文件的例子是什么? I tried several combinations of loaders, externals, and plugins on my configuration file, but I don't really get what they are doing and which ones should I use. 我在我的配置文件上尝试了几种加载器,外部和插件的组合,但我并没有真正了解他们正在做什么以及我应该使用哪些。 Thank you! 谢谢!

in my webpack.config.js (Version 1,2,3) file, I have 在我的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;
}

in my plugins array 在我的插件数组中

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

Now I have a file that only adds 3rd party libs to one file as required. 现在我有一个文件,只根据需要将第三方库添加到一个文件中。

If you want get more granular where you separate your vendors and entry point files: 如果您希望在分离供应商和入口点文件时更精细:

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

Note that the order of the plugins matters a lot. 请注意,插件的顺序很重要。

Also, this is going to change in version 4. When that's official, I update this answer. 此外,这将在版本4中发生变化。当这是官方的时候,我更新了这个答案。

Update: indexOf search change for windows users 更新: indexOf为Windows用户搜索更改

I am not sure if I fully understand your problem but since I had similar issue recently I will try to help you out. 我不确定我是否完全理解你的问题,但由于我最近有类似的问题,我会尽力帮助你。

Vendor bundle. 供应商捆绑。

You should use CommonsChunkPlugin for that. 你应该使用CommonsChunkPlugin in the configuration you specify the name of the chunk (eg vendor ), and file name that will be generated ( vendor.js ). 在配置中,您可以指定块的名称(例如vendor ),以及将生成的文件名( vendor.js )。

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

Now important part, you have to now specify what does it mean vendor library and you do that in an entry section. 现在重要的是,您必须现在指定vendor库的含义,并在条目部分中执行此操作。 One one more item to entry list with the same name as the name of the newly declared chunk (ie 'vendor' in this case). 还有一个项目到条目列表,其名称与新声明的块名称相同(在本例中为“供应商”)。 The value of that entry should be the list of all the modules that you want to move to vendor bundle. 该条目的值应该是您要移动到vendor包的所有模块的列表。 in your case it should look something like: 在你的情况下,它应该看起来像:

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

JQuery as global JQuery作为全球性的

Had the same problem and solved it with ProvidePlugin . 遇到了同样的问题并用ProvidePlugin解决了它。 here you are not defining global object but kind of shurtcuts to modules. 在这里,您不是要定义全局对象,而是模块化的类型。 ie you can configure it like that: 即你可以这样配置:

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

And now you can just use $ anywhere in your code - webpack will automatically convert that to 现在你可以在代码中的任何地方使用$ - webpack会自动将其转换为

require('jquery')

I hope it helped. 我希望它有所帮助。 you can also look at my webpack configuration file that is here 你也可以看看我在这里的 webpack配置文件

I love webpack, but I agree that the documentation is not the nicest one in the world... but hey.. people were saying same thing about Angular documentation in the begining :) 我喜欢webpack,但我同意这个文档并不是世界上最好的文档...但是嘿..人们在开始时对Angular文档说了同样的话:)


Edit: 编辑:

To have entrypoint-specific vendor chunks just use CommonsChunkPlugins multiple times: 要使入口点特定的供应商块多次使用CommonsChunkPlugins:

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

and then declare different extenral libraries for different files: 然后为不同的文件声明不同的extenral库:

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

If some libraries are overlapping (and for most of them) between entry points then you can extract them to common file using same plugin just with different configuration. 如果某些库在入口点之间重叠(对于大多数库),那么您可以使用相同的插件将它们提取到公共文件,只是使用不同的配置。 See this example. 这个例子。

In case you're interested in bundling automatically your scripts separately from vendors ones: 如果您有兴趣将自己的脚本与供应商分开自动捆绑:

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

You can read more about this feature in official documentation . 您可以在官方文档中阅读有关此功能的更多信息。

Also not sure if I fully understand your case, but here is config snippet to create separate vendor chunks for each of your bundles: 还不确定我是否完全理解您的情况,但这里是配置片段为每个捆绑包创建单独的供应商块:

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

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM