2

webpack version

2.2.1

I'm trying to add an additional manifest file in order to bypass webpacks runtime code injection issue and enable caching:

https://webpack.js.org/guides/code-splitting-libraries/#manifest-file

however, when passing a function into minChunks, in this case - in order to automatically get all the files that are in node_modules inside the vendor.js chunk - will result an unexpected outcome: only the last file in the array (manifest, in the example below) is generated.

webpack.config.js

entry: {
        bundle: "./src/index.tsx",
    },
    output: {
        filename: "[name].js?[chunkhash]",
        path: `${projectRoot}/dist`
    },
    plugins: [new webpack.optimize.CommonsChunkPlugin({
        names: ['vendor', 'manifest'],
        minChunks: function (module) {
            return module.context && module.context.indexOf('node_modules') !== -1;
        }
    })]

expected output

3 files: bundle.js, vendor.js and manifest.js

actual output

2 files: bundle.js, manifest.js

silicakes
  • 6,364
  • 3
  • 28
  • 39

1 Answers1

3

I observed that with the config above, the webpack v2.2.1, would create just the last one (i.e. manifest in your case) as it first thinks vendor as parent for the 'bundle' bundle and process ... next it thinks manifest as parent of 'bundle' bundle and process which would overwrite the previous processing. Finally while generating bundle, it create two bundle, the 'bundle' bundle and its parent - manifest bundle. I am not sure why it behaves like this with v2.2.1.

You would want to write your config like this

 plugins: [new webpack.optimize.CommonsChunkPlugin({
        name: 'vendor',
        chunks: ["bundle"], //optional
        minChunks: function (module) {
            return module.context && module.context.indexOf('node_modules') !== -1;
        }
    }), 
     new webpack.optimize.CommonsChunkPlugin({
      name: "manifest",
      chunks: ["vendor"],
      minChunks: Infinity
    })]

The trick here is that with the first plugin instance, you will be extracting the modules coming from node_modules to the vendor bundle. Since this is the parent common bundle, webpack will add its runtime code into vendor bundle (if the second instance of plugin is not added). Then with the application of second instance of the plugin, using minChunks as Infinity, you will not be extracting any module, but you will make the manifest bundle as parent bundle for vendor, hence, webpack will add its runtime code into the manifest bundle.

You need to make sure that manifest script should get executed first, then vendor script and finally bundle script. In other words, load them sequentially to avoid unexpected errors.

VISHAL DAGA
  • 4,132
  • 10
  • 47
  • 53
  • Exactly what I needed - thanks! How did you come to this conclusion though? I've been browsing all sorts of documentation in vain. – silicakes Feb 28 '17 at 06:58
  • 2
    Yes, documentation is not that good. I digged into the plugin code to find the solution for the issue – VISHAL DAGA Feb 28 '17 at 07:00
  • This worked as well for me. I also added: new webpack.optimize.CommonsChunkPlugin({ children:true }), between the two above. This move shared modules from children chunks into the main bundle. This makes a difference if you are using async routes or code splitting. – Joey Mazzarelli Mar 01 '17 at 23:56
  • 1
    I think that throwing away the webpack code throws the following `Uncaught ReferenceError: webpackJsonp is not defined` since the build doesn't contain the webpack references. – silicakes Mar 16 '17 at 14:35
  • Please note that I have mentioned in the last line - manifest script should get executed first as it define webpackJsonp. – VISHAL DAGA Mar 16 '17 at 16:55