首页 文章

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

提问于
浏览
161

我正在尝试做一些我认为应该可行的事情,但我真的无法理解如何从webpack文档中做到这一点 .

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

定义我的模块之间的依赖关系非常简单,但定义他们的第三方依赖关系似乎比我预期的更难 .

What I would like to achieve :对于每个应用程序,我想要有两个捆绑文件,一个包含必要的第三方依赖项,另一个包含我库中必需的模块 .

Example :我们假设我的库有以下模块:

  • a(需要:jquery,jquery.plugin1)

  • b(要求:jquery,a)

  • c(需要:jquery,jquery.ui,a,b)

  • d(需要:jquery,jquery.plugin2,a)

我有一个应用程序(将其视为唯一的条目文件),需要模块a,b和c . 此案例的Webpack应生成以下文件:

  • vendor bundle :使用jquery,jquery.plugin1和jquery.ui;

  • website bundle :模块a,b和c;

最后,我更喜欢将jQuery作为全局文件,因此我不需要在每个文件上都要求它(例如,我只需要在主文件上使用它) . 并且jQuery插件只是在需要时扩展$ global(如果它们可用于不需要它们的其他模块则不是问题) .

假设这是可能的,那么这个案例的webpack配置文件的例子是什么?我在我的配置文件上尝试了几种加载器,外部和插件的组合,但我真的不知道他们在做什么以及我应该使用哪些 . 谢谢!

4 回答

  • 51

    在我的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中发生变化 . 当这是官方的时候,我更新了这个答案 .

    Update: indexOf为Windows用户搜索更改

  • 11

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

    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 docs:http://webpack.github.io/docs/list-of-plugins.html#commonschunkplugin

  • 36

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

    Vendor bundle.

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

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

    现在重要的是,您必须现在指定它是什么意思 vendor 库并且您在入口部分中执行此操作 . 还有一个项目到条目列表,其名称与新声明的块名称相同(在本例中为'vendor') . 该条目的值应该是要移动到 vendor bundle的所有模块的列表 . 在你的情况下,它应该看起来像:

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

    JQuery as global

    有同样的问题并用ProvidePlugin解决了 . 在这里,您不是定义全局对象,而是模块的一种切换 . 即你可以这样配置:

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

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

    require('jquery')
    

    我希望它有所帮助 . 你也可以查看我的webpack配置文件here

    我喜欢webpack,但我同意这个文档并不是世界上最好的...但是嘿..人们在开始时对Angular文档说了同样的话:)


    Edit:

    要使入口点特定的供应商块多次使用CommonsChunkPlugins:

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

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

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

    如果某些库在入口点之间重叠(对于大多数库),那么您可以使用相同的插件将它们提取到公共文件,只是使用不同的配置 . 见this示例 .

  • 133

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

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

    您可以在official documentation中阅读有关此功能的更多信息 .

相关问题