Search code examples
javascriptwebpackwebpack-2code-splittingcommonschunkplugin

Split "vendor" chunk using webpack 2


I have code splitting config similar to official docs and everything works perfect - all my node modules are in "vendor" chunk (including "babel-polyfill"). But now I need to move babel-polyfill and all it's dependecies to separate chunk ("polyfills") to be able to load it before my vendor bundle. Any ideas how to do that?

My config:

...
entry: {
  main: './index.jsx'
},
...
new webpack.optimize.CommonsChunkPlugin({
  name: 'vendor',
  minChunks: function (module) {
    return module.context && module.context.indexOf('node_modules') !== -1;
  }
}),
new webpack.optimize.CommonsChunkPlugin({ name: 'manifest' })
...

Solution

  • Get dependencies

    You can read the package.json from babel-polyfill

    const path = require('path');
     
    function getDependencies () {
    
           // Read dependencies...
           const { dependencies } = require('node_modules/babel-polyfill/package.json');
    
           // Extract module name
           return Object.keys(dependencies);
    }
    

    Just call it (should return an array with the dependencies):

    const dependencies = getDependencies(); // ['module', ...]
    

    Detect polyfills

    Check if module is babel-polyfill or dependency:

     function isPolyfill(module){
         
         // Get module name from path
         const name = path.posix.basename(module.context)              
        
         // If module has a path 
         return name &&
    
         // If is main module or dependency
         ( name === "babel-polyfill" || dependencies.indexOf(name) !== -1 ); 
     }
    

    To remove babel-polyfill and dependencies just check if returns false

    new webpack.optimize.CommonsChunkPlugin({
        name: 'vendor',
        minChunks: function (module) {
    
            // If has path
            return module.context &&
    
            //If is a node-module
            module.context.indexOf('node_modules')!== -1 &&
    
            // Remove babel-polyfill and dependencies
            isPolyfill(module) === false;
        }
    })
    

    Create polyfills chunk

    To select only babel-polyfill and dependencies just check if returns true

    new webpack.optimize.CommonsChunkPlugin({
        name: 'polyfills',
    
        minChunks: function (module) {
    
            // If has a path
            return module.context &&
    
            //If is a node-module
            module.context.indexOf('node_modules')!== -1 &&
    
            // Select only  babel-polyfill and dependencies
            isPolyfill(module) === true;
        }
    })