paypal / react-engine

a composite render engine for universal (isomorphic) express apps to render both plain react views and react-router views
Apache License 2.0
1.45k stars 130 forks source link

replace full lodash inlined into client with lodash/assign #176

Closed zetlen closed 8 years ago

zetlen commented 8 years ago

This replaces the full build of lodash in the client library with only the assign method that the library requires. It reduces bundle size considerably.

I'm using the react-engine client library in a project, and I found that Webpack was producing very large builds, even though in my own code I had very few dependencies.

$ npm run bundle

> webpack --progress

    [0] Hash: f4f57f9976d22f813902648367b12ea11c157c7b
    Version: webpack 2.1.0-beta.20
    Hash: f4f57f9976d22f813902
    Version: webpack 2.1.0-beta.20
    Time: 8441ms
           Asset     Size  Chunks             Chunk Names
    js/bundle.js   322 kB       0  [emitted]  js/bundle.js
    css/main.css  81.4 kB       0  [emitted]  js/bundle.js
     [167] ./public/views .*\.jsx 193 bytes {0} [built]
        + 388 hidden modules
    Child extract-text-webpack-plugin:
            + 4 hidden modules

The culprit appeared to be lodash:

$ npm run analyze

> webpack --profile --json | webpack-bundle-size-analyzer

lodash: 615.66 KB (38.2%)
react: 615.51 KB (38.2%)
react-router: 101.96 KB (6.33%)
vxpattern-lib-paypal: 80.98 KB (5.03%)
history: 59.55 KB (3.70%)
  deep-equal: 3.8 KB (6.39%)
  warning: 1.76 KB (2.96%)
  <self>: 53.98 KB (90.7%)
fbjs: 32.19 KB (2.00%)
superagent: 29.14 KB (1.81%)
fuse.js: 22.35 KB (1.39%)
style-loader: 6.99 KB (0.434%)
react-engine: 4.88 KB (0.303%)
process: 4.4 KB (0.274%)
component-emitter: 3.11 KB (0.193%)
object-assign: 1.95 KB (0.121%)
warning: 1.76 KB (0.110%)
invariant: 1.48 KB (0.0920%)
css-loader: 1.47 KB (0.0914%)
query-string: 1.45 KB (0.0898%)
hoist-non-react-statics: 1.35 KB (0.0841%)
webpack: 1.03 KB (0.0639%)
strict-uri-encode: 182 B (0.0110%)
react-dom: 63 B (0.00382%)
<self>: 22.28 KB (1.38%)
<self>: 4.23 KB (100%)

In my own code, I was only using small slivers of lodash, based on the recommendation from the examples at lodash.com:

import reduce from 'lodash/reduce';
import map from 'lodash/map';

But the analyzer said it was coming from the whole library. After some research, I discovered that the client library uses lodash.assign by calling require('lodash').assign instead of require('lodash/assign'). When I made that change in my own react-engine branch, here was the resulting build:

 Hash: 74333e150c3ea67534e2
    Version: webpack 2.1.0-beta.20
    Time: 6437ms
           Asset     Size  Chunks             Chunk Names
    js/bundle.js   256 kB       0  [emitted]  js/bundle.js
    css/main.css  81.4 kB       0  [emitted]  js/bundle.js
     [169] ./public/views .*\.jsx 193 bytes {0} [built]
        + 391 hidden modules
    Child extract-text-webpack-plugin:
            + 4 hidden modules

react: 615.51 KB (55.8%)
lodash: 109.38 KB (9.91%)
react-router: 101.96 KB (9.24%)
vxpattern-lib-paypal: 80.98 KB (7.34%)
history: 59.55 KB (5.40%)
  deep-equal: 3.8 KB (6.39%)
  warning: 1.76 KB (2.96%)
  <self>: 53.98 KB (90.7%)
fbjs: 32.19 KB (2.92%)
superagent: 29.14 KB (2.64%)
fuse.js: 22.35 KB (2.03%)
style-loader: 6.99 KB (0.633%)
react-engine: 4.88 KB (0.442%)
process: 4.4 KB (0.399%)
component-emitter: 3.11 KB (0.282%)
object-assign: 1.95 KB (0.176%)
warning: 1.76 KB (0.160%)
invariant: 1.48 KB (0.134%)
css-loader: 1.47 KB (0.133%)
query-string: 1.45 KB (0.131%)
hoist-non-react-statics: 1.35 KB (0.123%)
webpack: 1.03 KB (0.0933%)
strict-uri-encode: 182 B (0.0161%)
react-dom: 63 B (0.00558%)
<self>: 22.28 KB (2.02%)
<self>: 4.23 KB (100%)

This one-line change results in a huge reduction in bundle size! 500KB before minification, and 66KB after.

samsel commented 8 years ago

thanks @zetlen

samsel commented 8 years ago

4.1.0 has this change now!