Understanding Webpack Configuration – [simplified]

Understanding webpack configuration with example codes is much easier than a detailed paragraph. Recently  Angular [Latest version] also use webpack for bundle the application. You can use webpack with any of the latest  Javascript libraries like react to bundle the application.

Here I add webpack configuration file and explain the concept and configuration behind that. Before that, I start with small heads up on webpack.

webpack configuration

Webpack is a module bundler for the modern javascript application, which bundles all the dependencies required by the application. Unlike Grunt or Gulp, This will process your application and build the dependency graph and make those dependencies into a smaller bundle. Finally, this gives a processed bundles as javascript which needs to be loaded by the application.

Webpack Configuration 

All the configuration are object available under the module.exports object.

module.exports = {
....
}

There are four important basic key configurations in webpack

Entry:

Configuration options determine the entry point dependency graph of the module bundle.

Output:

configuration options determine the output bundle path and its name.

Module Loaders :

As webpack only understand Javascript all the assets need to be bundled inside the webpack. These loader and rules are responsible for those actions.

Plugins :

This adds custom functionality to the modules at compilation. Most of the plugins have customization via options parameter.

In the below code snippet, I added Angular Hybrid App (Angular 1 + Angular 4 ) webpack configuration.

var path = require('path');
var webpack = require('webpack');
// Webpack Plugins
var CommonsChunkPlugin = webpack.optimize.CommonsChunkPlugin;
var autoprefixer = require('autoprefixer');
var HtmlWebpackPlugin = require('html-webpack-plugin');
var ExtractTextPlugin = require('extract-text-webpack-plugin');
var CopyWebpackPlugin = require('copy-webpack-plugin');
/* Create multiple reference for different css bundle. 
   For example If you need two css bundle then create a 
   seperate reference for each */
var allCss = new ExtractTextPlugin('./styles/styles.css');
module.exports = {
/* Devtool is used for module debugging. multiple option string are available. The Corresponding string is to debug the original source code */
    devtool: 'inline-cheap-module-source-map',
/* Output configuration specifies the output file destination and the name. These name get the value from entry configuration */
    output: {
        path: root('./min'),
        publicPath: '',
        filename: '[name].js',
        chunkFilename: '[id].chunk.js'
    },
/* Webpack bundles the file related to the dependency graph. This entry configuration is the starting point of that dependency graph. Mostly it is the first file to kick off application. You can also give multiple entries to create a multiple bundle.
Output takes the file name from the entry objects key */
    entry: {
        'polyfills': './app/polyfills.ts',  // Output polyfill.js
        'vendor': ['./app/vendor.ts'],      // vendor.js
        'app': './app/main.ts'              // app.js
    },

/* The resolver used to find the module code that needs to be included in the bundle for every such require/import statement */
 
    resolve: {
         extensions: ['.ts', '.js', '.json', '.css', '.scss', '.html'],
         alias: {
             'npm': __dirname + '/node_modules'
            }
    },
/* Module determine how the different types of modules inside the application need to be treated */
    module: {
/* rules are array of objects used to determine how the modules need to be treated with appropriate loaders created with the help of loaders */
        rules: [
            // The files with js extension are compiled using babel-loader and added to webpack's main bundle. exclude is used to skip the un wanted files. 
            {
                test: /\.js$/,
                exclude: /node_modules/,
                use: {
                    loader: 'babel-loader',
                }
            }, 
         // Files with ts extension are compiled  using awesome-typescript-loader
          {
                test: /\.ts$/,
                loaders: [{
                    loader: 'awesome-typescript-loader',
                    options: {
                        configFileName: 'tsconfig.json'
                    }
                }, 'angular2-template-loader']
            }, 
            // HTML are bundled using html-loader 
           {
                test: /\.html$/,
                loader: 'html-loader'
            }, 
           // other required application assets are bundled using normal file-loader
            {
                test: /\.(png|jpe?g|gif|svg|woff|woff2|ttf|eot|ico)$/,
                loader: 'file-loader?name=assets/[name].[hash].[ext]'
            }, 
            // As am using the scss here am using sass-loader for compiling and convert it into css. fallback is a kind os default loader used to bundle the css files.
            {
                test: /\.s?css$/,
                loader: allCss.extract({
                    fallback: "style-loader",
                    use: ['css-loader', 'sass-loader'],
                    allChunks: true,
                    publicPath: "./min"
                })
            }


        ]
    },
/* Plugins */ 
    plugins: [
        /* Extract text plugin reference used to seperate the css from the webpack bundle. If you have multiple reference call all the variable reference name separated by ',' */
        allCss,
        
        // Workaround for angular/angular#11580
        new webpack.ContextReplacementPlugin(
            // The (\\|\/) piece accounts for path separators in *nix and Windows
            /angular(\\|\/)core(\\|\/)@angular/,
            root('./', 'app'), // location of your src
            {} // a map of your routes
        ),
/*The CommonsChunkPlugin is an opt-in feature that creates a separate file (known as a chunk), consisting of common modules shared between multiple entry points */
        new webpack.optimize.CommonsChunkPlugin({
            name: ['app', 'vendor', 'polyfills']
        }),
/* The HtmlWebpackPlugin simplifies creation of HTML files to serve your webpack bundles */
        new HtmlWebpackPlugin({
            template: 'index.html'
        }),
        new ExtractTextPlugin('[name].css'),
    ],
/* dev server configuration */
    devServer: {
        historyApiFallback: true,
        stats: 'minimal'
    }
};
// Custom Helper functions
function root(args) {
    args = Array.prototype.slice.call(arguments, 0);
    return path.join.apply(path, [__dirname].concat(args));
}

 

Note: all the required loaders, plugin needs to be installed before use ( npm install loader-name –save-dev)

See Also: Know Basic TypeScript Features Before Starting Angular