Click here to Skip to main content
14,037,996 members
Click here to Skip to main content
Add your own
alternative version

Stats

3.7K views
3 bookmarked
Posted 24 Feb 2019
Licenced CPOL

Step by Step Migration - Webpack 3 to Webpack 4

, 26 Feb 2019
Rate this:
Please Sign up or sign in to vote.
This article details the migration steps from Webpack 3 to Webpack 4.

Introduction

Migrating from Webpack 3 to Webpack 4 is a very cumbersome process. I went through many articles and blogs to find a nice, easy and quick way of doing it. However, I could not find one single article that explains everything and lists out the pain points of migration. So, I decided to write something to help other fellow developers who are considering the upgrade in the near future.

Background

The first question is why do we need to upgrade to webpack 4. I am sure there are tons of articles over the internet to explain the benefits. So, I am skipping this part.

I'll explain upgrade of react/angular/other js bundles, less/Scss bundles. I am sure that once you get a handle on these assets, fonts/images are going to be a cakewalk.

Using the Code

Few things to consider before starting the migration are listed below:

  1. Update the npm version. It should be greater than 8.9.0. Run command npm -v to check the current version and to upgrade on Windows machine - just download node msi from here. For mac/linux, visit nodejs site and follow upgrade steps from there.
  2. Start with a new webpack.config.js file. It's always good to start from scratch and gradually do the migration with one asset type at a time. Rename the existing webpack.config.js file to webpack_old.config.js.
  3. Always try to use webpack-bundle-analyzer during migration to visualize which bundle file contains what packages. It helps in deciding which bundle to group in what chunk, therefore helps in optimising the chunks.
  4. Webpack 4 does not use extract-text-css-plugin, common-chunks-plugin, uglify-js-plugin (this works with earlier versions of webpack 4, not with the latest), so just get rid of these plugins. The alternate to these are mini-css-extract-plugin, splitChunksplugin (inbuilt in webpack 4) and terser-webpack-plugin consecutively.
  5. For the sass/scss transformation, you will need to add a postcss.config.js file inside your root folder. I'll attach this file for reference:
    //
    // postcss.config.js
    // 
    module.exports = {
        plugins: [
            require('autoprefixer')
        ]
    }
  6. Try to start with modifying the package.json file first, then update all the required migration packages.
  7. I got some error related to cosmiconfig. So, I had to include this package inside package.json file.

The package json should have minimum of these packages to run the webpack 4 for js/jsx/css/less/scss files.

Package.json

//
// minimum packages required to start with webpack 4 - define in package.json file
// 
    "autoprefixer": "^9.4.7",
    "babel-core": "^6.26.3",
    "babel-loader": "7.1.2",
    "babel-polyfill": "6.26.0",
    "babel-preset-env": "1.6.1",
    "babel-preset-es2015": "^6.24.1",
    "babel-preset-react": "6.24.1",
    "babel-preset-stage-3": "6.24.1",
    "clean-webpack-plugin": "^0.1.16",
    "cosmiconfig": "4.0.0",
    "less": "^3.9.0",
    "less-loader": "4.1.0",
    "mini-css-extract-plugin": "0.5.0",
    "node-sass": "4.11.0",
    "npm": "^5.8.0",
    "optimize-css-assets-webpack-plugin": "^5.0.1",
    "postcss-loader": "3.0.0",
    "sass-loader": "7.1.0",
    "style-loader": "0.23.1",
    "suppress-chunks-webpack-plugin": "0.0.4",
    "terser-webpack-plugin": "1.1.0",
    "toastr": "^2.1.4",
    "webpack": "4.29.0",
    "webpack-bundle-analyzer": "^3.0.4",
    "webpack-cli": "3.2.3",

Webpack.config.js

Define the const at the top in webpack.config.js file:

'use strict';
const path = require('path');
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const SuppressChunksPlugin = require('suppress-chunks-webpack-plugin').default;
const OptimizeCSSAssetsPlugin = require("optimize-css-assets-webpack-plugin");
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
const TerserPlugin = require('terser-webpack-plugin');

//Initialize PLUGINS
const MiniCssPlugin = new MiniCssExtractPlugin({
    filename: 'assets/css/[name].css'
});

// cleans 'dist' folder every time before a new build
//not required but nice to start with clean folder
const CleanPLugin = new CleanWebpackPlugin(
    ['./dist/js', './dist/css'], {
        verbose: false,
        dry: false
    });

Start with webpack module export and then define the config entries inside as follows:

module.exports = (env) => {

    //Define variables
    const isDev = env === 'development';
    const jsIdentifier = './assets/js/[name].js';
    const plugins = isDev ? [CleanPLugin, MiniCssPlugin, 
                    new BundleAnalyzerPlugin()] : [CleanPLugin, MiniCssPlugin];
   
    // build WEBPACK config
    const config = {};
    config.mode = env;
    config.watch = isDev;
    config.resolve = {
        extensions: ['.js', '.jsx']
    };
    config.devtool = 'source-map';
    config.entry =
        {
            'angularapp.min': './angularapp/app.js',
            sassStyle: './assets/scss/main.scss',
            lessStyle: './assets/less/main.less',
            'reactapp.min': './reactapp/index.js'
        };
    config.output = {
        path: __dirname,
        filename: jsIdentifier,
        chunkFilename: jsIdentifier
    };
    // you can get more information about the splitchunks plugin from webpack site.
    // This plugin is very powerful as you can define more than one entry inside cacheGroups
    // and further split the vendor chunks in 
    // as many small bundles as you want depending upon the 'test' value
    config.optimization = {
        splitChunks: {
            cacheGroups: {
                commons: {
                    test: /[\\/]node_modules[\\/]/,
                    name: 'vendor.min',
                    chunks: 'initial'
                }
            }
        },
        minimizer: [
            new TerserPlugin({
                sourceMap: isDev,
                cache: true,
                parallel: true,
                terserOptions: {
                    mangle: false,
                    keep_classnames: true,
                    keep_fnames: true,
                    output: {
                        comments: false
                    }
                }
            }),
            new OptimizeCSSAssetsPlugin({})
        ]
    };
    config.plugins = plugins;config.module = {
        rules: [
            {
                test: /\.(js|jsx)$/, exclude: /node_modules/,
                use: {
                    loader: 'babel-loader',
                    query: {
                        presets: ['es2015', 'react', 'stage-3']
                    }
                }
            },
            {
                test: /\.scss$/,
                use: [MiniCssExtractPlugin.loader,
                    {
                        loader: "css-loader", options: {
                            sourceMap: true
                        }
                    },
                    'postcss-loader',
                    {
                        loader: "sass-loader", options: {
                            sourceMap: true
                        }
                    }]
            },
            { // less loader for webpack
                test: /\.less$/,
                use: [MiniCssExtractPlugin.loader,
                    'css-loader',
                    'less-loader']
            }
        ]
    };
    return config;
};

There are two ways in which you can define the production/development configs in webpack:

  1. One way is using the --mode production (in package json command)
  2. The other, that I have used --env production flag (refer to the attached package.json file build scripts command)

There is no right or wrong approach. It totally depends upon how you want to define the configuration inside webpack.config.js file.

And that is all you have to change to migrate to webpack 4. I have attached the package.json and webpack.config.js file for reference.

Points of Interest

You can learn more about Webpack 4 configuration here.

History

  • 25th February, 2019: Initial version

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

Rahul Sabharwal
Technical Lead
Australia Australia
Have more than 10 years of experience in .Net Technologies.
Mostly focused on Web Applications in .Net MVC and Angular/React

You may also be interested in...

Comments and Discussions

 
QuestionGreat article, thanks for sharing Pin
Gunnar S15-Mar-19 23:05
memberGunnar S15-Mar-19 23:05 
AnswerRe: Great article, thanks for sharing Pin
Rahul Sabharwal8-Apr-19 1:36
memberRahul Sabharwal8-Apr-19 1:36 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

Permalink | Advertise | Privacy | Cookies | Terms of Use | Mobile
Web04 | 2.8.190425.1 | Last Updated 26 Feb 2019
Article Copyright 2019 by Rahul Sabharwal
Everything else Copyright © CodeProject, 1999-2019
Layout: fixed | fluid