jpt
jpt

Reputation: 162

How to include proper webpack bundles with multiple entry points?

What's the best way to automate the generation of (or even manually figure out) the script tags to use for an entry point in a multi-entry webpack setup?

I'm setting up an MVC application to use webpack for an enormous number of javascript dependency libraries. Since the MVC app loads a new page for each route, I have dozens of entry points, each with its own entry script.

I'm using code splitting and hash-naming (for cache-busting).

Since webpack is working out the dependency tree for each entry point, it seems to be doing a great job of breaking out the code into bundles for reuse. Here's my config (minus the code at the top and the plugins):

module.exports = {
    mode: "development",
    entry: {
        products_index: './Scripts/app/pages/Products/index.js',
        users_index: './Scripts/app/pages/Users/index.js',
    },
    output: {
        path: path.resolve(__dirname, 'dist'),
        filename: '[name].[contenthash:8].js',
    },    
    node: {
        fs: 'empty',
    },
    optimization: {
        runtimeChunk: 'single',
        splitChunks: {
            chunks: 'all',
            maxInitialRequests: Infinity,
            minSize: 0,
            cacheGroups: {
                vendor: {
                    test: /[\\/]node_modules[\\/]/,
                    name(module) {
                        // get the name. E.g. node_modules/packageName/not/this/part.js
                        // or node_modules/packageName
                        const packageName = module.context.match(/[\\/]node_modules[\\/](.*?)([\\/]|$)/)[1];

                        // npm package names are URL-safe, but some servers don't like @ symbols
                        return `npm.${packageName.replace('@', '')}`;
                    },
                },
            },
        },
    },

I've limited the entries to 2 for this example, but I've got many more.

The output in dist for this setup is:

 index.html                               
 npm.accounting.acb8cd33.js               
 npm.dropzone.1dcac339.js                 
 npm.jquery.7fe2b020.js                   
 npm.knockout-amd-helpers.356a8521.js     
 npm.knockout-punches.efb33702.js         
 npm.knockout.eaf67101.js                 
 npm.knockout.mapping.e01549c3.js         
 npm.moment.0f7e6808.js                   
 npm.sprintf-js.82f89700.js               
 npm.toastr.c6448676.js                   
 npm.webpack.2aab6b7b.js                  
 runtime.acfdeda3.js                      
 products_index.8ef7831b.js             
 products_index~users_index.02e60e46.js 
 users_index.42c4b7af.js                  

This approach is convincingly presented here and seems logical so I've used it.

Everything seems to go swimmingly until I have to create the script tags for this monster.

On the /users route, for example, how do I know which of these files to include? It seems webpack has done all this dependency mapping and left me to do it all again myself!

I can't find anything in in the Webpack documentation site that mentions how to best do this, except a discussion of the html-webpack-plugin which seems solely focused on creating one useless HTML file that just jams all the script tags into to a single file.

I must be missing something obvious here.

Upvotes: 3

Views: 3313

Answers (1)

jpt
jpt

Reputation: 162

I finally came across an answer buried in a response to an issue on the html-webpack-plugin github site.

If you specify the entry point chunk to the plugin, it correctly calculates the dependencies from there, so you can create a loop in your webpack config that builds the entry config and the plugin config parts and then add them to your config, like this:

var entry: {
        a: "./a",
        b: "./b",
        c: ["./c", "./d"]
};

var entryHtmlPlugins = Object.keys(entry).map(function(entryName) {
   return new HtmlWebpackPlugin({
      filename: entryName + '.html',
      chunks: [entryName]
  })
});

module.export = {
   entry: entry,
   //....
  plugins: [
      // ..
  ].concat(entryHtmlPlugins)
}

The issue page is here: https://github.com/jantimon/html-webpack-plugin/issues/299#issuecomment-216448896

At least in my preliminary testing, this seems to work. Would be great if it was mentioned somewhere in the docs.

Upvotes: 4

Related Questions