Webpack: Taking a long time to build

18,717

Solution 1

As discussed in the comments, here are the most obvious changes you could make to speed up your build:

  • UglifyJsPlugin and ExtractTextPlugin are very heavy in terms of their impact on your compilation time, while not actually presenting many tangible benefits in development. Check process.env.NODE_ENV in your config script, and enable/disable them depending on whether you're doing a production build or not.
    • In place of ExtractTextPlugin, you can use style-loader in development to inject CSS into the head of the HTML page. This can cause a brief flash of unstyled content (FOUC) when the page loads, but is much quicker to build.
  • If you're not already, use webpack-dev-server rather than just running Webpack in watch mode - using the dev server compiles the files in memory instead of saving them to disk, which further decreases the compile times in development.
    • This does mean you'll have to manually run a build when you want to have the files written to disk, but you'll need to do that to switch to your production config anyway.
  • Not sure if this has any impact on performance, but the resolve section of your config doesn't meaningfully differ from the defaults, and you should be able to remove it without causing any issues.

Solution 2

In my case I updated devtool property to false.

Solution 3

Article on Medium: https://medium.com/@gagan_goku/hot-reloading-a-react-app-with-ssr-eb216b5464f1

Had to solve the same problem for my React app (HELO) with SSR. Things get complicated with SSR, but thankfully webpack gets a lot faster if you specify --mode=development, because it does it in memory.

webpack-dev-server did not work for me because I need the client.js bundle for the SSR client to work properly. Here's my setup:

webpack.config.js:

const path = require('path');

module.exports = {
    entry: {
        client: './src/client.js',      // client side companion for SSR
        // bundle: './src/bundle.js',      // Pure client side app
    },
    output: {
        path: path.resolve(__dirname, 'assets'),
        filename: "[name].js"
    },
    module: {
        rules: [
            {
                test: /\.js$/,
                include: path.resolve(__dirname, 'src'),
                loader: "babel-loader",
                options: {
                    presets: [
                        '@babel/preset-env',
                        {'plugins': ['@babel/plugin-proposal-class-properties']},
                    ],
                }
            }
        ]
    },
    watchOptions: {
        aggregateTimeout: 1000,
        poll: 500,
        ignored: /node_modules/,
    }
};

package.json:

  "scripts": {
    // IMP: --mode=development
    "run-dev-ssr": "webpack --config webpack.config.js --watch --mode=development & babel src -d dist --watch & browser-refresh dist/server.js"
  }

.browser-refresh-ignore:

node_modules/
static/
.cache/
.*
*.marko.js
*.dust.js
*.coffee.js

.git/

# Add these files to ignore, since webpack is storing the compiled output to assets/ folder
src/
dist/

Build times without mode:

Hash: 81eff31301e7cb74bffd
Version: webpack 4.29.5
Time: 4017ms
Built at: 05/10/2019 9:44:10 AM

Hash: 64e10f26caf6fe15068e
Version: webpack 4.29.5
Time: 2548ms


Time: 5680ms
Time: 11343ms

Build times with mode:

Hash: 27eb1aabe54a8b995d67
Version: webpack 4.29.5
Time: 4410ms

Time: 262ms

Time: 234ms

Time: 162ms
Share:
18,717

Related videos on Youtube

Kal
Author by

Kal

Updated on September 15, 2022

Comments

  • Kal
    Kal over 1 year

    I have an issue with webpack build times in my react application. Everything builds fine but it takes a long time.

    Even I change just the JavaScript files the CSS rebuilds?

    Also the CSS compilation is taking a longer than I think it should be (correct me if I am wrong)?

    I am running a Core i7 with 16gb of Ram and the build is taking about a minute which is becoming very annoying during development when it's a one line change and you have to wait near enough a minute before you can see your changes in the browser?

    Is this the wrong approach?

    const CleanObsoleteChunks = require('webpack-clean-obsolete-chunks');
    const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
    const ExtractTextPlugin = require('extract-text-webpack-plugin');
    const DashboardPlugin = require('webpack-dashboard/plugin');
    const path = require('path');
    const webpack = require('webpack');
    
    const BUILD_DIR = path.resolve(__dirname, '../dist');
    const APP_DIR = path.resolve(__dirname, 'src/');
    
    const config = {
        devtool: 'source-map',
        entry: {
            "ehcp-coordinator": [
                APP_DIR + '/index.js'
            ]
        },
    
        output: {
            path: `${BUILD_DIR}/js/`,
            filename: '[name].js',
            chunkFilename: '[name]-chunk.js',
        },
    
        module: {
            rules: [
                {
                    test: /\.js$/,
                    exclude: /node_modules/,
                    use: {
                        loader: 'babel-loader',
                        options: {
                            presets: ['es2015', 'es2017', 'react', 'stage-0'],
                            plugins: ['transform-runtime', 'transform-decorators-legacy', 'transform-class-properties', 'syntax-dynamic-import',
                              ["import", {"libraryName": "antd",  "style": false}]]
                        }
                    }
                }, {
                    test: /\.less$/,
                    use: ExtractTextPlugin.extract({
                        use: [{
                            loader: "css-loader"
                        }, {
                            loader: "less-loader"
                        }]
                    })
                }
            ]
        },
    
        plugins: [
            new webpack.DefinePlugin({
                'process.env.NODE_ENV': "'development'"
            }),
            new webpack.optimize.UglifyJsPlugin({
                'sourceMap': 'source-map'
            }),
            new webpack.optimize.CommonsChunkPlugin({
                name: 'vendor',
                filename: '[name].js',
                minChunks(module, count) {
                    var context = module.context;
                    return context && context.indexOf('node_modules') >= 0;
                }
            }),
            new ExtractTextPlugin("../css/[name].css")
        ],
    
        resolve: {
            modules: [
                path.resolve('./'),
                path.resolve('./node_modules'),
            ],
            extensions: ['.js', '.json']
        }
    
    };
    
    module.exports = config;
    
    • Joe Clay
      Joe Clay almost 7 years
      I'd recommend only using UglifyJsPlugin and ExtractTextPlugin in production - they're pretty heavy in terms of compile time. Also, I think you can totally remove that resolve section of your config - it doesn't seem to meaningfully differ from the defaults.
    • Joe Clay
      Joe Clay almost 7 years
      Most people tend to either have a separate development and production config file, or (my preference) check process.env.NODE_ENV in the config script to conditionally enable/disable certain parts.
    • Kal
      Kal almost 7 years
      Sorry forgot to mention this is the dev webpack config not the prod build one. Aslo why does it build the CSS when say only the JS has changed?
    • Joe Clay
      Joe Clay almost 7 years
      You can continue to use less-loader and css-loader, just feed them into style-loader instead in development. This injects the CSS into the head of the page at run-time rather than having it in a separate file.
    • Joe Clay
      Joe Clay almost 7 years
      Also, if you're not already, use webpack-dev-server rather than just running Webpack in watch mode - using the dev server compiles the files in memory instead of saving them to disk, which further decreases the compile times in development. It means you have to manually run a build when you want to have the files output, but you'll need to do that to switch to your production config anyway.
  • Kal
    Kal almost 7 years
    Thank you, I will try the webpack-dev-server at somepoint, we run ours using nginx as a proxy so not sure but the others definitely improved the build time.