3 Things They Don’t Tell You About Angular Universal

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.

6 comments

  1. Thanks for the introduction into possible roadblocks with using Angular Universal.

    We are trying to use Angular Universal, for the main reason being to improve speed on low powered devices.
    As is mentioned on their site why to use Angular Universal:
    “Some devices don’t support JavaScript or execute JavaScript so poorly that the user experience is unacceptable. For these cases, you may require a server-rendered, no-JavaScript version of the app. This version, however limited, may be the only practical alternative for people who otherwise couldn’t use the app at all.”

    However, what we achieved was only that, as you also mentioned, something appears on the page (instead of a white page). Which could improve subjective appearance, but JS had still to be enabled.

    Do you know if it is possible (and any examples besides the ‘Hello World’ ones) to use Universal to render a complete site on the server, without relying on JS on the client side?

    1. For a completely non-javascript experience, I think it’s always going to be pretty hard to use Angular, even with Universal. So many interactions, form building etc rely on some level of javascript, even if the initial render doesn’t. So if you wanted to stick with JS for the backend, then you’re probably better off using NodeJS and building a full application that isn’t a SPA.

      1. Backend is PHP, communicating via API to Angular/Ionic components.
        It does not have to be complete non-javascript experience, but to rely less for slower devices (older phones have a hard time to crunch all the client side work put on them).

  2. What do you do if you have an angular/firebase app and you want links to unfurl and display nice thumbnails etc using those meta og:image tags?

    Sounds like the answer is: Can’t get there from here

    Have you actually deployed an Angular app using SSR? Or is it just brickwall after brickwall?

    Thanks!

    1. Brent

      We are using SSR just for the og meta tags. We are also using firebase. It works just fine. Just realize that your server is going to be connecting to firebase to get all this data before it renders and sends the page to the client. So you are also going to want to make a transfer state interceptor so that you aren’t hitting firebase twice for each initial page load.

  3. Sadly, I didn’t read this article before I started my Universal Angular project. 🙁 It completely reflects my experience with nguniversal.

Leave a Reply

Your email address will not be published. Required fields are marked *