How large is your app?

Just to have some references… How large is your app?

Mine is 4.29 MB. (Not yet optimized - probably should remove aws-sdk & meteor-node-stubs)

Is there a way to get a list for the packages with size > x kb? Perhaps we can help each other with tips to lower the footprint of our apps? (/cc @abernix)


3.4 MB not optimized and not done :slight_smile:

I like that idea, if we can extract reports out of the visualizer it’d be easier to share and discuss with others online as you suggested. Perhaps in the future the visualizer will have more intelligence in it to flag common issues.


My app is 300kB. But my app with modules - 4MB…


300kb is gzipped?

i could reduce it (gzipped) from 800kb to 500kb, but now it’s hard to reduce it more.

1 Like

Interesting @dr.dimitru, but I’ve a lot of modules that contribute to the initial bundle size which seems out of my control, react-dom, react-bootstrap, node stubs etc… so how did you manage to remove/delay all of those and still have a running app, I mean we don’t want to just load an empty shell and then delay loading everything after the first click?

Are you sure you haven’t oversplit your bundles?

Fantastic blog post by Ben btw, if anyone missed it.

Hmm, FontAwesome alone takes 1.1MB, what’s the best solution for that? Use a common CDN so that users may already have it cached? Move over to an SVG version so you can include only the icons you use?

…Actually I shouldn’t worry about that anyway as my app only has regular users and isn’t open to the public. I don’t know if code splitting would benefit me very much really.

Does anyone have example with dynamic imports and react-router v3?

Whether or not bundle-visualizer is installed, the raw data which the bundle-visualizer uses is available anytime an application is ran with --production or in the resulting bundle from meteor bundle. There will be a matching <hash>.stats.json file for each <hash>.js bundle.

The .stats.json files can be found in the following locations, when running:

  • meteor run --production
  • .meteor/local/build/programs/web.browser/*.stats.json
  • meteor build
  • bundle/programs/web.browser/*.stats.json

You could then do your own relatively simple filtering to find files over a certain size that you’d like to target.

Though I do admit a sliding-scale adjustment filter could be a nice feature for bundle-visualizer too!


Nice, will take a look at the generated stats.json. Another thought would be having the bundle analyzer built-in galaxy or hosted online…

1.085 MB, ~300 kb gzipped. MVP

Nice! is that the total bundle size? what view layer are you using?

I’m working on an example app that uses ReactRouter 3. I found the trick I needed here. See the Why bundle loader, and not import()? section further down that page.


Just so everyone knows, that meteor-node-stubs npm package lets you import stubs for Node built-in modules on the client, like assert and path. Only the modules you actually use get bundled, so don’t be fooled by the total size of node_modules/meteor-node-stubs. And it goes without saying (though this was kinda tricky) that stub modules can be imported dynamically if they’re not otherwise imported statically.


@alawi , @herteby ,

We don’t use

  • FontAwesome or alike pre-compiled iconic font sets
  • Bootstrap or other CSS framework/lib

We do use:

  • Google fonts, while font in the load process, or failed to be loaded, we’re trying to find best matching font from local visitor’ fonts in descending order
  • Compiled iconic fonts with only icons we need, and CSS it needs
  • SASS for internal styling with auto-prefixes - Not sure if it helps to save some bytes
  • Jade for Blaze templates - Not sure if it helps to save some bytes

Steps we have done:

  • After dynamic imports was introduced in Meteor 1.5 the fist idea was to swap our existing require(...) in FlowRouter routes rules to import(...), in a way described here. This is the most significant optimization our app ever faced.
  • Next we found most rarely used files which somehow got imported in the client/index.js (bundle), and moved to dependent modules or replaced with alternatives where is possible (saved ~100KB)
  • Momentjs, Stringjs, Diffjs, Numeraljs those heavy libs was imported to the bundle and weight around ~300KB altogether, we have tried to make those dependencies dynamically imported (and we did), but code complexity at this point with all internal async/await got out of the control so we decided to rollback, and have those libs in the main bundle.
  • Find a way to optimize Momentjs and Stringjs turn out we have been using only 5 features of Momentjs and 2 of Stringjs, so we compiled Momentjs and Stringjs with only features we need (saved ~180KB)
  • Review CSS/SASS rules (saved ~12KB)
  • Remove unused/useless meteor packages - reactive-dict, autoupdate, es5-shim, appcache, mobile-experience

Final results:

  • The js file size returned from meteor app (gzipped) - 247KB (Google Chrome DevTools - Network Tab)
  • The app size according to bundle-visualizer - 607KB (Yes, not ~300KB as at the first message, we brought back some NPM packages after tests)
  • The biggest packages we have now is Blaze and jQuery (both is tied to each other). Curious to see size of the apps with React. Anyone?


That is incredible! Awesome work!!


React. My app import code is only 100kb which helps. Relatively simple app.

1 Like

Final result a little bigger, but gzip compression is doing its thing.

What is unusual - we have tried to utilize dynamic imports for CSS/SASS files. After quick splitting and binding to the templates bundle size (according to bundle-visualizer) grew for ~80KB (0_o).

And either SASS was processed to CSS, transferred code over WebSockets wasn’t minified - is there any info about behind the scenes how dynamic imports acts with different types of files?

Is the size reported by bundle-visualizer minified and gzipped? I’m asking because the size it reports is significantly bigger than what website analyzers like GTmetrix report.

No, not gzipped. Yes, minified. Should be the byte to byte analysis. For more info see hashsum.stats.json where hashum is taken from main js file hashsum.js