Is My Angular Performance Normal?

by Stephen Fluin

2019-12-04

Is My Angular Performance Normal?
One of the most common things I do when encountering a new Angular app or team, is to take a look at their application in DevTools. There isn't a ton you can do to see the underlying code or architecture, but there's a a couple things you can do.
You can check to see what version of Angular they are using. Just search for ng-version in the elements tab. You could also just have installed my Angular Inspector extension.
The other thing you can do is to see how big and fast the application is. Just switch over to the network tab and look at how much your browser has to download to run and display the first page of an application. To me, this is one of the most important performance considerations as the initial load time of your users is almost entirely determined by your initial bundle size.
Network tab can show JS resources size and transfers
You could have as much code as you wanted if you lazy loaded it at the right time, and users would never know, but the initial load is what could cost you millions if your site is too slow for your users.

What's Normal?

Here's a few example Angular apps (from successful companies) that you can see in the wild and their inital bundle size as reported by DevTools:
  • Delta.com: 4.2MB
  • Forbes.com: 5.7MB
  • Android Messages: 1.1MB
  • Grubhub: 3.4MB

For comparison, here's some non-Angular JavaScript bundle sizes:
  • microsoft.com is 1.4MB
  • amazon.com is 7.5MB
  • theverge.com is 9.6MB
  • Wikipedia pages are 223KB
  • reddit.com is 4.9MB
  • netflix.com is 4.2MB (for logged in users)
  • twitter.com is 3.5MB

Keep in mind that for some of these, it's not as bad as it sounds. Server side rendering or prerendering can mean that a lot of this JS is not in the critical path for page rendering, which is one GREAT way to partially get around initial JS size. Some of these also conditionally serve JS based on heuristics about anticipated user activity, which is another great strategy. Serving different bundles to different user types (fast network, slow network, powerful device, slow device) is also another advanced strategy that will change these numbers.
Looking at how big the top web properties are getting today... Yeah, your app is probably normal. But is that who you want to be?

Normal is not good enough

It's worth noting that the moment you start pushing past a few hundred kilobytes, your users (especially on mobile) are going to have to start to wait for you. Waiting kills user experience, it kills engagement, it kills sales.
If you used almost every single feature of Angular on your home page, including browser animations, forms, the router, http, and some Angular Material components (by the way, don't load everything on your home page), but wrote no code yourself, your entire application would be less than 400kb, which means that any time your application exceeds 800 or 900kb, it's because you are asking your users to run lots of your code to generate your pages.
If you look at the coverage report available in the bottom pane, the situation is almost dismal. Most of the time, LESS than 50% of the JavaScript sent down with a page is executed on initial load. A bunch of this code is for is error handling, and some of it can be Angular's fault, but a lot of the unused JavaScript comes from us just not being aware of the problem.
delta.com code coverage shows 64% unused code in main.js
FYI this blog is about 482KB today, and sometimes benefits from prerendering.

The Main Culprits

How does this happen? How do we go from a blank application with all of the platform features at 400KB to a real application in the several megabytes range? The most common cause is marketing and advertising tools. Everything from your analytics package, to your user tracking, to your help desk tools can end up costing your usres and harming user experience, when they were built to try to help.
Here's some of the top offenders I've seen polluting bundle size and performance:
  • SiteCatalyst
  • fbevents
  • ruxit
  • LivePerson

There are hundreds more, but these are ones that I've seen multiple times when inspecting large applications.

What do I do?

Decide when, where, and how you want to set the balance between user experience, load performance, customer engagement, and intelligence.
Analyze your bundles ruthlessly. Generate source maps for every chunk and every bundle, and look to see what's in them? I recommend source-map-explorer. Don't be afraid to ask why you are making your users pay for certain features, capabilities, and dependencies.
If you really want a single button a user can press to get a live person, why not separate the actual functionality into a lazy route, and only render the button until a user requests it?
Hopefully this post has made you feel better and worse at the same time. If you have small bundles, congratulations! Keep it up! If you have large bundles, you're probably in good company, but we all need to strive to do better for our users.