Over the past couple of months I’ve been doing battle with an Angular Universal project. Angular Universal is Angular’s answer to Server Side Rendering or SSR for short. Why use SSR? In most cases it’s for SEO purposes but in some cases it also gives “perceived” performance.
For SEO, when opening a link to an SSR website, Angular renders the complete (Or semi-complete) page on the server, and returns the HTML that can be read by search engines (and other robots).
When I say “perceived” performance, what I mean is that because it’s atleast semi-rendered, a user doesn’t see a flash of a blank screen like you normally get with regular Angular apps. I personally don’t think it really returns the complete page any faster than a regular Angular App, but the first paint is more “complete” than that of a regular Angular app.
It sounds good on the surface, but just try and have a quick search for how many people are actually using Angular Universal in production – there’s not many. Almost every tutorial you find on the subject is the Angular Universal equivalent of a “Hello World”. I won’t say I’m an expert on Angular Universal, but I wanted to write this article to maybe show you a couple of things that every tutorial leaves out of the conversation.
Library Support Is Rough
The first thing you probably learn when using Universal is that when the page is rendered on the server, it doesn’t have access to a couple of really important (common) javascript paradigms. Among them, you can’t access the window object (Since this refers to the browser window of which there isn’t one when doing server side rendering), you can’t access things like localStorage or any sort of memory that might live inside a browser window like Session Storage. Cookies are also a bit of an issue for obvious reasons.
Angular recommends you wrap things that need to access these objects inside a method called isPlatformBrowser so that you can check if you are in that moment doing server side rendering or if you are doing it in a browser. (More info here https://github.com/angular/universal/blob/master/docs/gotchas.md).
But, that’s with your code. What about something like an authentication library that uses localStorage? Like the MSAL library from Microsoft that allows your javascript application to integrate with Azure AD. They have a great Angular package that makes authentication a cinch. But they obviously haven’t gone and wrapped everything in browser checks. Why would they muddle their code with that when very very few people are using Angular Universal anyway?
And I ran into this same problem many times over. Even just libraries that try and access the window object (which has to be pretty common in javascript), they are going to completely bomb out when running inside Angular Universal. Of course, you can always fork the code or try and add in a bunch of browser checks yourself, but the point is is that all those libraries that were plug and play on your last project suddenly become a headache to get integrated.
Development Is Extremely Slow And Confusing
Let’s face it, building Angular Universal bundles are slow. When you have a plain Angular app and you run “ng serve”, it’s snappy. The watchers are fast and changing a couple of lines typically only takes a couple of seconds to recompile. I’ve found Angular Universal to be the exact opposite. Often with recompiles taking almost the exact same time as the initial compile. Those jokes back in the day of “can’t work, code recompiling” when you were working on mainframes are back!
I also found debugging of Angular Universal apps incredibly complicated and often confusing. You see it’s only the *initial* request that is server side rendered. As you click around the site, you are then inside a regular Angular app and therefore everything is client side. But common debugging tools like console.log() become very confusing to follow because if it’s an initial request, that log will be written on the server, not in the browser, all subsequent logs will be written to the browser. Same goes for any debugging tool you might use. The initial request would be like debugging a typical Express application, but all subsequent requests can be debugged just fine from the browser. Trying to bring a new developer up to speed is pretty damn difficult.
Documentation Is Terrible
Finally. The documentation is terrible. Angular Universal has one, yes one, page of documentation here : https://angular.io/guide/universal. That’s it. I even had to log a bug that the sample application they provide doesn’t actually compile at all. And they closed it was they were “working on it”. So not sure how hard it is to just provide a working example of an Angular Universal app, but evidently it’s still not been updated.
Beyond the official documentation, you typically rely on other examples and blogs floating around on the web that really only scratch the surface of what Angular Universal does. If you run into any roadblocks at all, you are pretty much on your own because as far as I’ve seen, no one actually uses Angular Universal in any large commercial capacity (Happy to be proven wrong though!).
Should You Use Angular Universal?
I’m a big believer in using the right tech for the right purpose. As it stands right now, I believe that if you need server side rendering, then don’t use a client side javascript framework to do it. While it’s not too hard to turn any app into Angular Universal. On any project of reasonable size, you’ll start hitting roadblocks thick and fast and soon realize that Angular Universal is a fun POC, but not a commercial offering.