Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

React webpack bundle size is large

I have a website that developed using react which has a single page, but the production bundle size is 1.11 MiB. I'm using firestore,firebase storage, material-UI, react-redux for this app app works well everything is fine except the bundle size.

enter image description here

I used webpack-bundle-analyzer to analyse the bundle size, It seems like nodemodules tooks large size. Here I have added the screenshot. enter image description here

My webpack config file

    const path = require('path');
var CompressionPlugin = require('compression-webpack-plugin');
const TerserPlugin = require("terser-webpack-plugin");
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;

module.exports = {
  mode: 'production',
  entry: './src/public/index.js',
  plugins: [
    new BundleAnalyzerPlugin({
      generateStatsFile : true
    }),
    new CompressionPlugin({
      deleteOriginalAssets: false,
      filename: "[path][base].gz",
      algorithm: "gzip",
      test: /\.js$|\.css$|\.html$/,
      threshold: 10240,
      // Compress all assets, including files with `0` bytes size
      // minRatio: Infinity

      // Compress all assets, excluding files with `0` bytes size
      // minRatio: Number.MAX_SAFE_INTEGER
      minRatio: 0.8,
    })

  ],
  optimization: {
    nodeEnv: 'production',
    minimize: true,
    concatenateModules: true,

  },

  module: {
    rules: [{
        test: /\.(jpe?g|png|gif|svg)$/,
        loader: 'image-webpack-loader',
        // This will apply the loader before the other ones
        enforce: 'pre',
      },
      {
        test: /\.m?js$/,
        exclude: /node_modules/,
        use: {
          loader: 'babel-loader',
          options: {
            presets: ['@babel/preset-env'],
            plugins: [
              ["@babel/plugin-proposal-object-rest-spread", {
                "definitions": {
                  "process.env": {
                    "NODE_ENV": "\"production\""
                  }
                }
              }],
              ['babel-plugin-transform-imports',
                {
                  '@material-ui/core': {
                    // Use "transform: '@material-ui/core/${member}'," if your bundler does not support ES modules
                    'transform': '@material-ui/core/esm/${member}',
                    'preventFullImport': true
                  },
                  '@material-ui/icons': {
                    // Use "transform: '@material-ui/icons/${member}'," if your bundler does not support ES modules
                    'transform': '@material-ui/icons/esm/${member}',
                    'preventFullImport': true
                  }
                }
              ]
            ]
          }
        }
      }

    ]
  },
  output: {
    path: path.resolve(__dirname, 'build'),
    filename: 'bundle.js'
  }
};

I don't know what I missed here to reduce node-modules size. If we have any other option to reduce bundle size please give me a suggestion for that.

like image 986
Curvegraph Avatar asked Apr 17 '21 09:04

Curvegraph


3 Answers

MaterialUI, lodash and webpack support Tree Shaking. Since you used webpack-bundle-analyser, I am assuming your build process utilises webpack. So your options are the following:

You can use Webpack's Tree Shaking Guide.

Material UI also has a Minimizing Bundle Size Guide.

In general, a large part of bundle size reduction is dead code elimination.

Once you have done that, you might want to follow React's Code Splitting guide to ensure that the initial load is faster.

like image 116
ManavM Avatar answered Oct 20 '22 21:10

ManavM


You could import lodash funcions separataly

import get from 'lodash/get'

instead of

import { get } from 'lodash'

But I bet this will not reduce drastically your bundle size

like image 42
Vinicius Katata Avatar answered Oct 20 '22 22:10

Vinicius Katata


If you want to reduce the build size, you can import functions in this way

import groupBy from 'lodash/groupBy';

Instead of this

import { groupBy } from 'lodash';

The former will fetch the contents of the entire lodash library and the latter will only fetch one specific chunk of the it. Thus reducing the build sizes by a huge amount.

like image 1
shivaraj bakale Avatar answered Oct 20 '22 22:10

shivaraj bakale