Decrease react app bundle size using webpack-merge
Tags: webpack, react, javascript
Published: 2020-07-23 11:59:56

Hello,

First of all I am very new to writing articles. Please bear with me.

While developing a react app we generally have a local host server, hot-reloading and [strong source mapping](https://webpack.js.org/configuration/devtool/) which don't need in production for obvious reasons. So it doesn't make sense to have these tools unnecessarily which increases the bundle size.

To minimize bundle size by having these tools only in development we can make use of a plugin called [webpack-merge](https://github.com/survivejs/webpack-merge). So, to achieve this we are going to follow the below steps.

##Step1:
Install `webpack-merge` using `yarn add --dev webpack-merge` or `npm install --save-dev webpack-merge`.

##Step2:
split the existing webpack.config.js to three files.

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/muw2wmgp9m6402mfi5el.jpg)

**webpack.common.js** It contains the common code which we use for development and production both

```
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
const CopyPlugin = require('copy-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const localConfig = require('./src/common/localConfig');

module.exports = {
  entry: {
    index: './src/index.js'
  },
  module: {
    rules: [
      {
        test: /\.js$/,
        include: path.resolve(__dirname, 'src'),
        use: {
          loader: 'babel-loader',
          options: {
            presets: ['@babel/preset-env', '@babel/preset-react'],
            plugins: [
              '@babel/plugin-transform-runtime',
              '@babel/plugin-proposal-class-properties'
            ]
          }
        }
      },{
        test: /logo.svg$/,
        loader: 'svg-url-loader'
      }, {
        test: /abcd-.*\.(?:le|c)ss$/,
        loaders: [
          MiniCssExtractPlugin.loader,
          'css-loader',
          'less-loader',
        ]
      }
    ],
  },
  plugins: [
    new CleanWebpackPlugin({ cleanStaleWebpackAssets: false }),
    new HtmlWebpackPlugin({
      template: "./src/index.ejs",
      inject: true,
      filename: "./index.html",
      templateParameters: {
        'localConfig': localConfig
      }
    }),
    new MiniCssExtractPlugin({
      filename: '[name]-[contenthash].css',
      chunkFilename: '[id]-[contenthash].css',
    }),
    new CopyPlugin(
      [
        { from: 'public', to: '' },
      ],
    ),
  ],
  output: {
    filename: '[name].[hash].bundle.js',
    path: path.resolve(__dirname, 'dist'),
  },
  optimization: {
    splitChunks: {
      chunks: 'all',
    },
  },
};
```
(the above is only sample code. It doesn't to match with yours)

**webpack.dev.js** It contains the development code which includes local server, hot reloading etc.
```
const { merge } = require('webpack-merge');
const common = require('./webpack.common');

module.exports = merge(common, {
  mode: 'development',
  devtool: 'inline-source-map',
  devServer: {
    port: 3003,
    https: true,
    contentBase: './dist',
    hot: true,
    allowedHosts: [
      'local.dev.abcdefg.net'
    ],
    public: 'https://local.dev.abcdefg.net:3003/',
    publicPath: '/',
    open: {
      // This doesn't actually work
      app: ['firefox']
    }
  }
});
```
**webpack.prod.js** It contains the production related code which doesn't include much (specifically)
```
const { merge } = require('webpack-merge');
const common = require('./webpack.common');

module.exports = merge(common, {
  mode: 'production',
  devtool: 'source-map'
});
```

##Step3:
run `npm run build`

Now you can compare the build size before and after. :)