TIL: Analyzing Angular App’s Bundle Size with source-map-explorer
Today I learned how to use source-map-explorer to analyze an Angular app’s bundle file(s).
This post is based on
@angular/cli
1.0.3 and@angular/*
4.1.2.
In JavaScript Jabber podcast episode 249: Loading and Optimizing Web Applications with Sam Saccone and Jeff Cross, one important takeaway I got was we should measure our app’s performance before optimize it. With helps of tools, we can get more in-depth information about how the app perform, and how we can optimize it properly.
Script file size (or bundle size) is one of the key things we can optimize for a JavaScript heavy app. The app should not deliver unnecessary scripts to the user, where “unnecessary scripts” could mean unused modules/imports in the bundle. This is generally the case when the app imports the whole module but actually use a few small parts of it.
To get the information of what modules are bundled within the bundle file in an Angular app, we can use source-map-explorer to display graphical overview of what’s inside the bundle file.
Source-map-explorer takes a bundle .js
file with its generated sourcemaps, turns them into a treemap: a graphical representation of different parts in the bundle, which is something easier to understand and to dig into.
Installing source-map-explorer
$ npm install -g source-map-explorer
Using source-map-explorer with an Angular app
Source-map-explorer needs a .js
file with its sourcemaps, by default, $ ng build
command of Angular CLI creates the sourcemaps file (.map
) along with main.bundle.js
in /dist
directory. We can use source-map-explorer to generate and open the treemap by passing the file path of main.bundle.js
to the command:
$ source-map-explorer dist/main.bundle.js
It will then opens generated treemap (surprisingly fast!) as HTML format on a browser with this view:
We can drill into each part of the bundle by clicking on it. It will “zoom” into that specific part with more visible details.
However, this gives information only our app’s scripts: only files in src/app
directory. This is because Angular CLI separates our vendor scripts from the app’s scripts by putting them invendor.bundle.js
. We still don’t know how much vendor scripts take in our app.
One way to solve this issue is to tell Angular CLI to put vendor scripts in the main bundle file by setting --vendor-chunk
option of the CLI to false
when running ng build
command.
$ ng build --vendor-chunk=false
Then we can use source-map-explorer again with main.bundle.js
file. This time we can see both vendor and app scripts together, and how are the sizes of each part related to others.
The treemap above was created with JIT build, and environment
of development
.
In an app we are working on, we are still using JIT by default but with production
environment. Our build is then created with these flag:
$ ng build --aot=false --vendor-chunk=false --target=production --sourcemaps
--aot=false
to build in JIT mode. (We had some issues with AOT mode at the time of writing)--vendor-chunk=false
to put vendor scripts in the main bundle.--target=production
to enable production build.--sourcemaps
to enable sourcemaps generation which is disabled when we set the target toproduction
.
We can see that the app’s scripts in src
directory takes actually ~18% of the bundle, while Angular itself takes 45%. From looking at the treemap, we can see some potential optimization already:
- Build in AOT mode: removes Angualr Compiler from the bundle
- Eliminate unnecessary imports which are not used in this app (moment.js locales, which was by the way mentioned in the podcast as well, RxJS operators, lodash universe, etc.)
- Tree shaking
I’m pretty excited about how detailed information we can get with just this one tool, and how much we could optimize this app’s bundle size down to.
Let me know if you have some techniques to optimize Angular apps. Happy coding and optimizing! 🏀