Adventures in bundle optimization
It was time to explore the optimization possibilities for the app I've been working on.
Our main bundle was 1.25 MB (515 kB gzip). create-react-app
handles the build and produces the bundle with the source map.
All bundle visualization tools I remember looking at required webpack config tweaking. But source-map-explorer is simple to use:
source-map-explorer \
build/static/js/main.9998a4e8.js \
build/static/js/main.9998a4e8.js.map
It produces beatiful dependency hierarchy:
My first surprise was the size of Firebase with its 300 kB. I noticed storage.js
and messaging.js
which correspond to newer Firebase 3 features we did not use.
There should be a way to include only necessary modules. After a quick search I found an answer in the NPM readme of the firebase
package.
Instead of
import firebase from "firebase";
you can do
import firebase from "firebase/app";
import "firebase/auth";
import "firebase/database";
This achieved a small win in 25 kB. Bundle size was down to 491 kB gzip.
Next, I was looking at 130 kB iconv-lite
. I had no idea where it came from. npm still doesn't have a nice command to explain why the module is in node_modules
. I had to unleash my shell skills:
npm ls | grep -B 5 iconv-lite
├─┬ lokka-transport-http@1.6.1
│ ├─┬ node-fetch@1.6.3
│ │ ├─┬ encoding@0.1.12
│ │ │ └── iconv-lite@0.4.15
Aha, lokka
! This is the GraphQL client we use.
I couldn't find a way to reduce the size of node-fetch
through webpack bundling. But it took me only about an hour to switch to a different GraphQL client (Apollo Client).
From 515 kB to 284 kB, much better. Time to get some users.