Search code examples
webpack-2

Unable to concatenate multiple JS files using Webpack


I am using Webpack 2 in my project to transpile and bundle ReactJS files along with a few other tasks. Here's what my config looks like:

var webpack = require("webpack");
const ExtractTextPlugin = require("extract-text-webpack-plugin");
var config = {
    module: {
      loaders: [
        {
          exclude: /(node_modules)/,
          loader: "babel-loader",
          query: {
            presets: ["es2015", "react"]
          }
        },
        {
          test: /\.scss$/,
          use: ExtractTextPlugin.extract({
            fallback: "style-loader",
            use: ["css-loader", "sass-loader"]
          })
        }
      ]
    },
    plugins: [
      new webpack.optimize.UglifyJsPlugin({ mangle: false, sourcemap: false }),
      new ExtractTextPlugin({
        filename: "../../public/dist/main.css"
      })
    ],
};
var indexConfig = Object.assign({}, config, {
    name: "index",
    entry: "./public/javascripts/build/index.js",
    output: {
       path: __dirname + "/public/dist",
       filename: "index.min.js",
    },
});
var aboutConfig = Object.assign({}, config, {
    name: "about",
    entry: "./public/javascripts/build/about.js",
    output: {
       path: __dirname + "/public/dist",
       filename: "about.min.js"
    },
});

// Return Array of Configurations
module.exports = [
    indexConfig, aboutConfig
];

As evident, I am using multiple build configurations for JS, one for each page. Now, I need to add some Bootstrap JS to the mix for which I also need JQuery and Tether. Thus, I have the following 3 files in my library folder:

  1. jquery-3.2.1.min.js
  2. tether.min.js
  3. bootstrap.min.js

I need these 3 files to be concatenated and bundled along with the main JS files being emitted by Webpack (e.g., index.min.js, etc.). To do so, I modified my entry item thus:

entry: {
  a: "./public/javascripts/lib/jquery-3.2.1.min.js",
  b: "./public/javascripts/lib/tether.min.js",
  b: "./public/javascripts/lib/bootstrap.min.js",
  c: "./public/javascripts/build/index.js"
}

However, doing so throws the following error:

ERROR in chunk a [entry]
    index.min.js
    Conflict: Multiple assets emit to the same filename index.min.js

    ERROR in chunk b [entry]
    index.min.js
    Conflict: Multiple assets emit to the same filename index.min.js

    ERROR in chunk c [entry]
    index.min.js
    Conflict: Multiple assets emit to the same filename index.min.js

Obviously this is because Webpack is expecting multiple output files for multiple entry items. Is there any way to overcome this problem? An existing question illustrating a similar problem doesn't seem to have any acceptable answer at the moment.

UPDATE:

Tried using the Commons chunk plugin as suggested by terales, but Webpack threw the following error this time:

ERROR in multi jquery tether bootstrap
    Module not found: Error: Can't resolve 'jquery' in '/home/ubuntu/panda'
     @ multi jquery tether bootstrap

    ERROR in multi jquery tether bootstrap
    Module not found: Error: Can't resolve 'tether' in '/home/ubuntu/panda'
     @ multi jquery tether bootstrap

    ERROR in multi jquery tether bootstrap
    Module not found: Error: Can't resolve 'bootstrap' in '/home/ubuntu/panda'
     @ multi jquery tether bootstrap

    ERROR in chunk vendor [entry]
    index.min.js
    Conflict: Multiple assets emit to the same filename index.min.js

Solution

  • Your libs shouldn't be entries. They called "vendors" in Webpack's terms.

    See minimum working example repo.

    In your code you should implicitly extract common vendor chunk:

    var config = {
        entry: {                       // <-- you could make two entries
            index: './index.js',       //     in a more Webpack's way,
            about: './about.js'        //     instead of providing array of confings
        },
        output: {
            filename: '[name].min.js',
            path: __dirname + '/dist'
        },
        module: {
            loaders: [
                // Fix error 'JQuery is not defined' if any
                { test: require.resolve("jquery"), loader: "expose-loader?$!expose-loader?jQuery" },
            ]
        },
        plugins: [
            // this assumes your vendor imports exist in the node_modules directory
            new webpack.optimize.CommonsChunkPlugin({
                name: 'vendor',
                minChunks: function (module) {
                    return module.context && module.context.indexOf('node_modules') !== -1;
                }
            })
        ]
    };