xkawi / react-universal-saga

Universal React Starter Kit ft. Redux Saga
https://react-universal-saga.herokuapp.com
MIT License
186 stars 33 forks source link

Large bundle size #6

Closed MehdiZonjy closed 7 years ago

MehdiZonjy commented 7 years ago

First of, Thanks for sharing this repo with the community.

I noticed that the client bundle size is rather large, about 780kb after minification. any idea on how to bring it down a bit?

I managed to cut it down to around 500 by removing "react-bootstrap" (which i won't probably be using) ,and changing Lodash imports from import _ from 'lodash'; to import zip from 'lodash/zip'

The bundle still seems a bit large, do you have any recommendation on how to trim it down to a more reasonable size?

xkawi commented 7 years ago

@MehdiZonjy thanks for checking this repo. Unfortunately I do not have definitive answer for this. Your best bet would be to remove other dependencies that you do not really need. I tried to remove some dependencies as well, my best result is like yours, around 500kb.

You can check other alternatives mentioned in readme. In particular, can checkout react-universally-skinny.

MehdiZonjy commented 7 years ago

@xkawi thanks for the reply. react-universally-skinny seems nice although atfirst glance i like your files structure more. I'll take a deeper look into it.

I did more digging tonight and here is what I found: I think there is a way to reduce the bundle by atleast 90kb. First I added the following flag to webpack build npm script to generate a "stats.json" file

webpack --verbose --colors --display-error-details --config webpack/prod.config.js --profile --json > stats.json

Then I imported "Stats.json" Here to get the dependency graph nodes

I noticed a couple of clusters contributing to the large bundle size

  1. babel-polyfill is adding about 60kb
  2. babel transform-runtime (27kb)
  3. normalizer is importing many lodash functions (20kb)
  4. There is a large chunk of modules included from ./src/containers/DevTools (90kb)
  5. the rest is react/redux related code + the actual github demo app.
    • regarding babel-polyfill, sadly I don't have access to an old browser on my machine to test which features of it are necessary and which aren't. If the bundle is only using Promises it would be possible to swap it with one of the promise polyfills out there which might be smaller.
    • babel-transform-runtime is a must.
    • Normalizer is being used in the demo app, but probably i won't be using it in my project.
    • DevTools seems to be the culprit here. I don't think you meant to add it to the production bundle. It's being included because it's imported from './src/containers/index.js' once i removed the import, I managed to save 90kb.

Also I think further optimization might be possible by switching to Webpack2 and making use of its TreeShaking feature.

xkawi commented 7 years ago

@MehdiZonjy thanks for sharing your finding, it's very helpful. I will try to find time to dig deeper myself. In fact, it would be great if you can do PR with all the optimisation that you made. 😃

Regarding Webpack2, I haven't tried it myself, so any input would be very helpful in this area.

MehdiZonjy commented 7 years ago

@xkawi definitely. I'll submit a PR containing my optimizations regarding the bundle size soon.

Treeshaking should work by default. I tried to upgrade to webpack2 the other day but I ended up with lots of errors relating to styles bundling, simple changes to the structure of webpack config file, and extract-text-webpack-plugin migration issues. I managed to fix the second and third issues but I couldn't get the styles bundling to work; I must have missed something.

xkawi commented 7 years ago

@MehdiZonjy merged your PR. very helpful to dig even deeper.

I am currently trying to remove babel-polyfill, because it seems that it is not used at all. My first observation when commenting all the require(babel-polyfill) is that, everything seems to work fine without it.

removing babel-polyfill, and a few unused dependencies, will reduce the bundle size to ~362Kb.

will report more findings here.

MehdiZonjy commented 7 years ago

@xkawi Thanks for merging the PR. I have an old LG P970 phone running on Android 4,1 from (2012). I tested the webapp using the good old Android Browser. Unfortunately, It doesn't work when commenting out babel-polyfill module. Sadly debugging on this old browser is rather difficult so I can't track down the exact problem. But I reckon that it needs Promise and Object.assign from babel-polyfill and maybe some of the new Array operations.

Is supporting such a relic browser worth adding an extra 60kb to the bundle? a possible solution might be to comment out babel-polyfill by default, but mention somewhere in the README that in order to support old browsers the user has to add babel-polyfill manually.

MehdiZonjy commented 7 years ago

Good news, I managed to get the bundle to work on my old phone's browser without babel-polyfill. I replaced babel-polyfill with with PolyFill.io and It seems to be working properly.

i added the following to the HTML component.

 <script src="https://cdn.polyfill.io/v2/polyfill.min.js"></script>

now the bundle is down to 377kb. The size of polyfill.io varies depending on the client browser which is the perfect solution.

xkawi commented 7 years ago

that's great. I was about to recommend that as well. Yes, it is the perfect solution indeed. 😃

I replace babel-polyfill with PolyFill.io and able to build without any error. Just wondering if that's the case on your side as well? just to confirm.

I also remove a few unused dependencies, including react-bootstrap, as it is not necessary for a base setup. Partly also because I overlook those unused dependencies when porting my own project into this repo. Now the bundle size is around ~366Kb.

I will make a commit for these changes soon. (Update: 691862a)

Think the next thing that I can try is to re-write the example to use as less dependencies as possible. And probably try to migrate to webpack2. Any chance that you get the style bundling working? since that's the issue that you faced earlier.

MehdiZonjy commented 7 years ago

I can confirm that PolyFill.io is working fine.

unfortunately i haven't made any progress regarding webpack2

xkawi commented 7 years ago

thanks for the confirmation. will close this issue for now, feel free to re-open again (or create new issue) if anyone have something to share or discuss about this. thanks @MehdiZonjy for your contribution. 😃