Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Webpack: how to bundle entries to multiple common chunks with CommonsChunkPlugin?

Say I have two pages Page1 and Page2, both of them use some library(vendors) like jquery backbone which I want to be extracted as a single file, then I want the shared modules(exclude the vendors) to be extracted in another single file, this is the webpack config:

function listFiles(srcpath) {
    return fs.readdirSync(srcpath).filter(function (file) {
        return fs.statSync(path.join(srcpath, file)).isDirectory();
    });
}
var createEntry = function (src) {
    var dest = {
        vendor: ["backbone", "underscore"]
    };
    var files = listFiles(src);
    files.forEach(function (dir) {
        var name = dir;
        dest[name] = src + "/" + dir + "/entry.js";
    });
    return dest;
};

//each sub directory contains a `entry.js` as the entry point for the page
var entries = createEntry("./app/pages");//    {vender:['jquery','backbone'],page1:'src/page1/entry.js',page2:'src/page2/entry.js'    }

var config = {
    resolve: {
        root: path.resolve('./app/'),
        extensions: ['', '.js']
    },

    plugins: [
        new webpack.optimize.CommonsChunkPlugin("vendor", "vendor.js", Infinity),
        new webpack.optimize.CommonsChunkPlugin({
            name: 'common',
            filename: 'common.js',
            minChunks: 2
        })
    ],
    entry: entries,
    output: {
        path: './../main/webapp/static/dist',
        filename: '[name].js',
        publicPath: '/static/dist'
    }
};
module.exports = config;

However with the above config:

common.js contains webpack runtime,

page1.js contains page1 specified modules and shared modules

page2.js contains page2 specified modules and shared modules

Which means page1.js and page2.js contains too many repeat codes.

Then I tried to change the config:

var entries = createEntry("./app/pages");
var chunks = [];
for (var k in entries) {
    if (k === 'vendor')
        continue;
    chunks.push(k);
}


new webpack.optimize.CommonsChunkPlugin("vendor", "vendor.js", Infinity),
new webpack.optimize.CommonsChunkPlugin({
    name: 'common',
    filename: 'common.js',
    minChunks: 2,
    chunks:chunks
}),

Then

common.js contains the webpack runtime and the vendor libraries, and the shared modules

vendor.js contains the webpack runtime and the vendor libraries.

page1.js contains page1 specified modules

page2.js contains page2 specified modules

It seems it get closer, but the common.js should not contain the vendors

Anything wrong?

like image 707
hguser Avatar asked Mar 10 '16 05:03

hguser


1 Answers

If you want multiple common chunk bundles, you'll have to specify all chunks details for each common bundle like shown in the example:

var config = {

    entry: {
        vendor: ["backbone", "underscore"],
        common: "./app/pages/common/entry.js",
        page1: "./app/pages/page1/entry.js",
        page2: "./app/pages/page2/entry.js"
    },

    plugins: [
        new webpack.optimize.CommonsChunkPlugin({
            name: "vendor",
            chunks: ["vendor"]
        }),
        new webpack.optimize.CommonsChunkPlugin({
            name: "common",
            chunks: ["common"]
        })        
    ]
};

Note that the chunks option of CommonsChunkPlugin refers to the name of the entries you target. As you want to split vendor from common, you have to explicitly say that you only want vendor entry in vendor common-chunk and same for common.

like image 150
ngasull Avatar answered Oct 16 '22 04:10

ngasull