skip to Main Content

I have a small React project. The bundle.js generated by Webpack is 6.3Mb. How can I decrease the size to be <2.0Mb? (2Mb is still big but acceptable). Complete source code is at github

webpack.config.js

module.exports = {
    devtool: 'inline-source-map',
    entry: [
        './app/components/app.jsx'
    ],
    output: {
        path: './public',
        filename: 'bundle.js'
    },
    resolve: {
        modulesDirectories: ['node_modules', 'app'],
        extensions: ['', '.js', '.jsx', '.scss']
    },
    module: {
        loaders: [
            {
                test: /.jsx?$/,
                exclude: /node_modules/,
                loaders: ['happypack/loader']
            },
            {
                test: /.scss$/,
                loaders: [
                    'style',
                    'css',
                    'autoprefixer?browsers=last 3 versions',
                    'sass?outputStyle=expanded'
                ]
            },
            {
                test: /.(jpe?g|png|gif|svg)$/i,
                loaders: [
                    'url?limit=8192',
                    'img'
                ]
            }
        ]
    },
    plugins: [
        new webpack.HotModuleReplacementPlugin(),
        new webpack.NoErrorsPlugin(),
        new HtmlWebpackPlugin({
            title: 'Fullstack Rebel',
            template: './app/templates/index_template.ejs'
        }),
        new HappyPack({
            loaders: ['babel?presets[]=react,presets[]=es2015']
        })
    ]
};

package.json

{
  "name": "fullstackcms",
  "version": "0.0.1",
  "description": "A Content Management System Made of NodeJS, MongoDB, React, Redux and Bootstrap",
  "main": "index.js",
  "scripts": {
    "dev": "webpack-dev-server --colors"
  },
  "repository": {
    "type": "git",
    "url": "https://github.com/dsun29/fullstackcms"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "dependencies": {
    "autoprefixer-loader": "^3.1.0",
    "body-parser": "^1.14.2",
    "connect-mongo": "^1.3.2",
    "css-loader": "^0.24.0",
    "express": "^4.13.3",
    "express-session": "^1.14.1",
    "file-loader": "^0.9.0",
    "history": "^1.17.0",
    "img-loader": "^1.2.2",
    "immutable": "^3.7.6",
    "jquery": "^3.1.0",
    "lodash": "^4.0.0",
    "mongodb": "^2.2.10",
    "node-sass": "^3.4.2",
    "node-twitter-api": "^1.8.0",
    "react": "^15.3.1",
    "react-bootstrap": "^0.30.3",
    "react-dom": "^15.3.1",
    "react-google-login": "^2.5.1",
    "react-modal-dialog": "^3.0.2",
    "react-redux": "^4.0.6",
    "react-router": "^2.7.0",
    "react-tinymce": "^0.5.1",
    "react-twitter-widgets": "^0.2.4",
    "redux": "^3.0.5",
    "redux-thunk": "^2.1.0",
    "reqwest": "^2.0.5",
    "routes": "^2.1.0",
    "sass-loader": "^4.0.1",
    "style-loader": "^0.13.0",
    "url-loader": "^0.5.7"
  },
  "engines": {
    "node": "0.12.0"
  },
  "devDependencies": {
    "babel": "^6.5.2",
    "babel-cli": "^6.4.0",
    "babel-core": "^6.17.0",
    "babel-eslint": "^6.1.2",
    "babel-loader": "^6.2.5",
    "babel-plugin-transform-runtime": "^6.15.0",
    "babel-polyfill": "^6.16.0",
    "babel-preset-es2015": "^6.16.0",
    "babel-preset-react": "^6.16.0",
    "babel-preset-stage-3": "^6.11.0",
    "babel-regenerator-runtime": "^6.5.0",
    "babel-register": "^6.16.3",
    "babel-runtime": "^6.11.6",
    "chai": "^3.4.1",
    "chai-immutable": "^1.5.3",
    "eslint": "^3.4.0",
    "eslint-config-airbnb": "^10.0.1",
    "eslint-plugin-import": "^1.14.0",
    "eslint-plugin-jsx-a11y": "^2.2.1",
    "eslint-plugin-react": "^6.2.0",
    "happypack": "^2.2.1",
    "html-webpack-plugin": "^2.22.0",
    "mocha": "^3.0.2",
    "react-hot-loader": "^3.0.0-beta.3",
    "webpack": "^1.13.2",
    "webpack-dev-server": "^1.14.0"
  }
}

Some results from webpack-bundle-size-analyzer

active-event-stack: 402.98 KB (17.3%)
  lodash: 401.81 KB (99.7%)
  <self>: 1.17 KB (0.292%)
react-bootstrap: 382.86 KB (16.4%)
  warning: 1.76 KB (0.461%)
  <self>: 381.1 KB (99.5%)
react-router: 156.83 KB (6.73%)
  history: 49.02 KB (31.3%)
    warning: 1.76 KB (3.60%)
    <self>: 47.26 KB (96.4%)
  warning: 1.76 KB (1.13%)
  query-string: 1.45 KB (0.922%)
  hoist-non-react-statics: 1.35 KB (0.864%)
  <self>: 103.24 KB (65.8%)
immutable: 139.14 KB (5.98%)
react-overlays: 69.06 KB (2.97%)
  warning: 1.76 KB (2.56%)
  <self>: 67.29 KB (97.4%)
dynamics.js: 60.12 KB (2.58%)
react-tinymce: 49.09 KB (2.11%)
  lodash: 43.66 KB (88.9%)
  <self>: 5.43 KB (11.1%)
babel-runtime: 45.11 KB (1.94%)
  core-js: 40.78 KB (90.4%)
  <self>: 4.33 KB (9.59%)
jss: 42.23 KB (1.81%)
fbjs: 32.61 KB (1.40%)
react-modal-dialog: 26.36 KB (1.13%)
redux: 22.36 KB (0.960%)
react-redux: 19.37 KB (0.832%)
reqwest: 18.76 KB (0.806%)
dom-helpers: 15.56 KB (0.668%)
lodash: 12.9 KB (0.554%)
uncontrollable: 9.57 KB (0.411%)
style-loader: 6.99 KB (0.300%)
css-vendor: 6.11 KB (0.263%)
react-prop-types: 6.04 KB (0.260%)
react-center-component: 5.87 KB (0.252%)
react-jss: 5.34 KB (0.229%)
node-libs-browser: 5.17 KB (0.222%)
  process: 5.17 KB (100%)
  <self>: 0 B (0.00%)
react-google-login: 3.99 KB (0.171%)
deep-equal: 3.8 KB (0.163%)
keycode: 2.7 KB (0.116%)
object-assign: 1.95 KB (0.0836%)
invariant: 1.48 KB (0.0636%)
css-loader: 1.47 KB (0.0632%)
jss-vendor-prefixer: 1.39 KB (0.0596%)
jss-nested: 1.18 KB (0.0506%)
jss-camel-case: 1.13 KB (0.0484%)
hoist-non-react-statics: 1.09 KB (0.0470%)
classnames: 1.08 KB (0.0462%)
symbol-observable: 1.07 KB (0.0461%)
jss-px: 936 B (0.0393%)
redux-thunk: 529 B (0.0222%)
webpack: 251 B (0.0105%)
strict-uri-encode: 182 B (0.00763%)
react-dom: 63 B (0.00264%)
is-browser: 22 B (0.000923%)
reqwest xhr2: 15 B (0.000629%)
<self>: 119.37 KB (5.13%)

5

Answers


  1. You are using ‘inline-source-map’ as devtool option. This adds sourcemaps inside your bundle, which are actually bigger than code itself. Try another option from webpack documentation.

    Login or Signup to reply.
  2. Your bundle is huge because of the source map. When creating the bundle, remove this line:

    devtool: 'inline-source-map'
    

    This will also remove the source map during development however, so can do something like this in package.json:

    “scripts”: {
    “dev”: “webpack-dev-server –colors”,
    “build”: “webpack -p”
    },

    Webpack -p will start the build mode for webpack, and will also minify your code, making it smaller.

    And in your webpack.config.js:

    const args = require('yargs').argv;
    const build = args.p;
    
    
    devtool: build ? undefined : 'inline-source-map',
    

    This will remove the source map when building.

    There are better methods to identify build, such as NODE_ENV, and you should look at the devtool options, if you need a source map in production.

    Login or Signup to reply.
  3. There are a couple of things that you can do. I suggest to create two configurations of webpack. First for development where we don’t care about bundle size and second for production where bundle will be optimized.

    1. Remove completely source-map (delete devtool line). You don’t need it in production mode.

    2. Use production mode. Add this entry to plugins

      plugins: [
          new webpack.DefinePlugin({
              'process.env': {
                  'NODE_ENV': JSON.stringify('production')
              }
          })
      ],
      
    3. Use webpack -p for building

    4. To minimize size of libraries you should only import functions that
      you use. For example if you need a few functions from lodash like
      forEach, orderBy, map.

      import forEach from 'lodash/forEach'
      import orderBy from 'lodash/orderBy'
      import map from 'lodash/map'
      
    Login or Signup to reply.
  4. Old question, but would question the need for active-event-stack which seems pretty huge for what it is. If it’s a child dependency then consider something else. Also, the bootstrap library you’re using is huge, you may be able to just use the specific components you want and reduce the output.


    Comment, came into this answer as I have an application using material-ui with a few components and some router interactions, and my uncompressed bundle size is 873k including styles and a couple images. You should also gzip it, and serve it gzipped by the webserver. Mine gzipped is (180KB)… YMMV.

    Login or Signup to reply.
  5. This may still be of interest to some people so I’ll throw in an additional answer…

    React functional components, aka React hooks, introduced in V16 use less code than class-based components so that’s another option

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search