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

后端 未结 4 1730
我寻月下人不归
我寻月下人不归 2020-11-28 17:51

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.

I am writing a JavaSc

相关标签:
4条回答
  • 2020-11-28 18:03

    in my webpack.config.js (Version 1,2,3) file, I have

    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.

    Update: indexOf search change for windows users

    0 讨论(0)
  • 2020-11-28 18:06

    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

    0 讨论(0)
  • 2020-11-28 18:12

    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. in the configuration you specify the name of the chunk (e.g. vendor), and file name that will be generated (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. One one more item to entry list with the same name as the name of the newly declared chunk (i.e. '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. in your case it should look something like:

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

    JQuery as global

    Had the same problem and solved it with ProvidePlugin. here you are not defining global object but kind of shurtcuts to modules. i.e. 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

    require('jquery')
    

    I hope it helped. you can also look at my webpack configuration file that is here

    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 :)


    Edit:

    To have entrypoint-specific vendor chunks just use CommonsChunkPlugins multiple times:

    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:

    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.

    0 讨论(0)
  • 2020-11-28 18:14

    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.

    0 讨论(0)
提交回复
热议问题