What’s the state of Angular Universal and AOT?
I’ve spent a good deal of the last week looking at Angular Universal and Ahead of Time (AOT) compilation. Until now, I had been waiting to dig into them because it was clear they were still in the experimental/alpha stages.
However, I decided that I want to update the DevIntent website from
1.5.7 to the latest version of Angular over the Christmas break!
Since this is a marketing website, I need it to be super fast, especially on mobile, and have excellent SEO! I’m also using this as a testing ground for some work on an upcoming client project.
Current website status
Times listed for No throttling / Regular 3G.
459ms / 3760ms DOMContentLoaded
920ms / 13850ms Load
This is fairly typical of a smaller Angular 1.5.x application that is using a few libraries (Angular Material, Font Awesome, etc.) and is hosted on Firebase Hosting. It’s fine on desktop with broadband internet, but not good enough on a mobile 3G device.
Bust out the Angular-CLI
My first choice is generally the Angular-CLI because I believe in what they are doing to make Angular more approachable to new users. I use it as much as I can so that I can provide feedback, open bug reports, and even submit PRs.
The first step was to see if Universal and AOT was working yet in the CLI. I found that they were both working, just not together. The Angular-CLI does not support Angular Universal. It does support AOT, but there are around 63 open issues related to AOT.
There is a separate fork for a version of the CLI that supports Universal, but it doesn’t support AOT. It appears that they created this fork because the Angular-CLI team didn’t have the resources to support Universal.
Grab one of the hot seed projects
From the latest presentations that I’ve seen at conferences, I knew that there were a number of great Angular seeds out there.
The first one I looked at was angular-seed from Minko Gechev. It is really well-known, has 3,344+ stars, and supports AOT, Docker, etc. Unfortunately it doesn’t support Angular Universal or Webpack. After using Webpack with the Angular-CLI, I decided that I don’t want to use another bundler in my non-Angular-CLI projects.
I checked into Universal Starter from the Angular Universal team. It uses Webpack and has basic support for AOT. But it is really minimal and doesn’t include support for SASS/SCSS. I decided that I might come back to it.
Angular2-Webpack-Starter from AngularClass was another that caught my eye since it obviously supported Webpack, but it also had a lot of the other stuff ready to go. This included Router, HTTP, Forms, Hot Module Reload (HMR), Async/Lazy Routes, Material Design, and tests! It also has a great list of guides and tips like setting up SASS/SCSS. Unfortunately, it doesn’t yet support AOT compilation or Angular Universal.
Found a number of seeds w/ #AngularUniversal support, but they all seem to be broken (#ngMaterial2 / #AOT) or stuck on #Angular 2.1.— Michael Prentice (@Splaktar) December 15, 2016
Finally picking a seed
I settled on giving Anthony’s (qdouble)
fork of angular2-webpack-starter a shot. It
combines all the great stuff from the original angular2-webpack-starter with support for AOT and
Universal! One thing I quickly noticed was that the project is stuck on an older version (
Angular (latest is
After a lot of research, it became obvious that changes to Angular core in v2.2 and v2.3 broke Angular Universal. Apparently the Angular core team has realized that this is a problem.
But I just saw this https://t.co/eJtyJEVZrw which mentions that #Universal is moving to angular core. #ngMaterial2 is waiting on the move.— Michael Prentice (@Splaktar) December 14, 2016
Because of this, they decided a couple weeks ago to move key pieces of Angular Universal into the
Angular core. Unfortunately, a number of key people have been on vacation since this decision
was made. So we’re stuck in this state where using Angular Universal means staying on Angular
This also means that support for Angular Universal in a new version of Angular will have to wait for
at least v4 which just entered
Angular 4.0.0-beta.0 is out. You're wondering why it's Angular 4? Read about the reasoning behind here: https://t.co/9AhXTMnlXc #angular— Juri Strumpflohner (@juristr) December 15, 2016
Measuring the benefits
The main purpose of the chosen seed/starter is performance (i.e. Angular Universal, Webpack 2, and AOT compilation). I checked the README for some stats for nerds (i.e. perf goodies) but sadly found none. Thus, I set to gathering some performance stats on the current build of the starter.
- Times listed for No throttling / Regular 3G.
- 29 requests
- 5.8 MB
- 1300ms / 66000ms DOMContentLoaded
- 1350ms / 66000ms load
npm run universal
- 16 requests
- 363 KB
- 928ms / 4480ms DOMContentLoaded
- 973ms / 5020ms load
npm run compile + npm run prodserver
- 16 requests
- 301 KB
- 432ms / 3530ms DOMContentLoaded
- 495ms / 3930ms load
Universal + AOT
npm run universal:aot or npm run compile:universal+ npm run prodserver
- 16 requests
- 392 KB
- 494ms / 4410ms DOMContentLoaded
- 535ms / 5030ms load
Tests Ran on
Chrome 57.0.2951.0 canary (64-bit)
MacBook Pro (Retina, 15-inch, Mid 2014)
2.8 GHz Intel Core i7
16 GB 1600 MHz DDR3
OS X El Capitán 10.11.6 (15G1212)
Now I know that Universal and AOT are still undergoing a lot of breaking changes and needed improvements, but I found it a little odd that the combination (Universal + AOT) was slower than the build with AOT alone.
Since the angular-cli isn’t supporting Universal + AOT yet, I was looking to find a solid seed for Universal, AOT, Webpack 2, Material 2, SCSS, etc. and this one seems to be the closest that I can find which isn’t significantly broken.
Perhaps part of this issue is that the app doesn’t have an appShell (it’s just a white “Loading…” page), but either way I’m not sure I should go to the extra trouble of running a NodeJS server for Universal at this point. I could just host a client-only app in Firebase Hosting using their Edge CDN w/ AOT and maybe that would be even faster than the numbers above.
SEO is something that I really need, but I’m not convinced that Universal will work properly here
and deliver the desired results. There’s some
possible hacks discussed in the
universal-starter project where the meta tags can be manipulated. However, Angular’s new
Meta Service just landed in Angular
thanks to Dzmitry Shylovich! Unfortunately Universal isn’t compatible with the latest versions of
It appears that I should just stick with AOT compilation and wait until Universal gets better support from the Angular core team (in progress, no ETA).
Thankfully the chosen starter makes that a well-supported option in addition to supporting these configurations used in the benchmarks above. This is what enabled the ability to gather these numbers using different approaches, while keeping the code-base exactly the same. Thanks to Anthony for the hard work on this starter and for sharing what’s been working for him on his projects!