Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Don't rebuild webpack bundle if entry files didn't change

Tags:

webpack

Consider we have a webpack config like this:

entry: {
    app: './main.js',
    lib: './vendor.js',   
}

The vendor.js file only consists of a bunch of requires to libraries from node_modules. 99% of the time I build the bundle(s) the output lib.js bundle is exactly the same.

Can I somehow tell webpack that if the vendor.js file didn't change (or preferrably some other custom condition like checking the modification date of lib.js and package.json to detect if I possibly have new versions of modules in node_modules) I do not want to rebuild the lib.js bundle? It takes a substantial amount of time on my CI server because of typescript transpliations etc.

like image 414
kamilkp Avatar asked Apr 28 '16 07:04

kamilkp


People also ask

How to create a Webpack bundle?

Webpack creates a bundle file from the source files. In webpack configuration file, there is an option to provide the file name of the output bundle file. If the name is static, then the browser loads the file for the first time from the server. From the second time, it will take the file from browser cache.

How does Webpack serve the result from memory?

It serves the result from memory through the Express instance it uses to serve the files. You can test this by changing the path to localhost:8080/webpack-dev-server/bundle.js in your html file and if you run webpack-dev server the changes should show up. The proper way to handle it is to update your webpack.config.js with a publicPath property:

How to get the name of the output bundle file?

In webpack configuration file, there is an option to provide the file name of the output bundle file. If the name is static, then the browser loads the file for the first time from the server. From the second time, it will take the file from browser cache. That will create a problem if bundle file is updated in the server.


1 Answers

As far as I am aware Webpack only really knows if a file will be the same once it has already built it because so many factors can change the file contents. The modified date of a file really does not provide enough information to determine that it should not be built again so I'd advise against it or you'll probably end up breaking your builds at some point and leaving people confused.

However if you did feel the need to do this though you could if you wanted make your Webpack config dynamic and use fs.stat to read vendor.js and then only add it as an entry if its changed. Something roughly like this:

var fs = require('fs');

var config = {
    entry: {
        app: './main.js'
    }
    ...
};

var stats = fs.statSync('./vendor.js');
if (new Date(stats.mtime).getTime() > process.env.LAST_VENDOR_BUILD_TIMESTAMP) {
    config.lib = './vendor.js';
    // Then save new Date().getTime() somewhere like a DB and
    // pass it in as LAST_VENDOR_BUILD_TIMESTAMP on next build.
}

module.exports = config;

As you can see the only way to solve your problem is that each and every build needs to have knowledge about previous builds to achieve this. This is undesired as your builds should be discrete and not care about previous build results.

Alternatively you should also try excluding some node_modules from the build if it is taking a really long time. I've not built typescript projects before but I exclude all of node_modules and my builds run much faster. Other than that, you shouldn't really mind your CI server being a little slow, at least it will be robust.

like image 84
Matt Derrick Avatar answered Oct 20 '22 14:10

Matt Derrick