What is Universal?

The official site states that Universal is: Server-side Rendering for Angular apps. However, here is how I like to define Angular Universal:

Universal is Angular for the Headless Web.

You do not need a browser container anymore, aka a WebView, to run Angular. Since it is not tied to the DOM, Angular can run anywhere, where there is a JavaScript runtime.

I shamefully borrowed the term “Headless Web” from Paul Kinlan. I strongly recommend reading his blog post where he gives his vision about what the Web should be in the future.

The big picture

Before using Universal, let’s take a look at the overall architecture.

Angular Universal High Level Architecture

This diagram illustrates the ability of Universal to run your typical Angular Web application outside the browser. Obviously we need a JavaScript runtime, that is why we support Node.js (which is powered by the V8 engine) by default. However, some efforts have started to support other server side technologies such as PHP, Java, Python, Go … and I’m happy to say that Universal already works on the .Net stack thanks to Steve’s work.

Now that your application can be interpreted outside the browser —let’s take a server as an example— the client which requested your SPA will receive a static fully rendered page of the requested route/URL. This page contains all the related resources, i.e. images, stylesheets, fonts… even data coming through your Angular service.

In fact, Universal takes care of handling and fetching all required data before rendering the page— that you usually fetch with Angular’s Http service. Universal is capable of rewiring some of the default Angular’s providers so they can work on the target platform. There is more. When the client receives the rendered page, it also receives the original Angular application — we only help your application loads almost instantly. Once loaded, Angular takes care of the rest.

But what happens when Angular bootstraps over the rendered page? Won’t we have some sort of states issues? Or maybe the user would want to use your application just after they see the rendered page — which makes sense? How would you then handle state? How does Universal itself handle state?

We got you covered…

In fact, Universal comes bundled with the Preboot.js library which sole role is to make sure of that both states are synced.

What Preboot.js does under the hood is simply and intelligently record the events that occur before Angular bootstraps; and play them back after Angular has completed loading. Simple, isn’t it?

Renderers

Universal is made possible thanks to Angular’s rendering abstractions. In fact, when you write your application code, that logic gets parsed into an AST by Angular’s compiler — we are really simplifying things here . That AST is then consumed by the Angular’s rendering layer, which uses an abstract renderer that is not tied to the DOM. Angular allows you to use different renderers. By default Angular ships the DOMRenderer so your application can be rendered in a browser, which is probably 95% of the use cases.

And that’s where Universal comes in. Universal comes with bunch of prerenderers, for all the mainstream technologies and build tools.

Dependency Injection and Providers

Another area where Angular shines in is with its DI system. Angular is in fact the only front-end framework that implements this design pattern which allows to accomplish so many great tasks easily (see IOC). Thanks to DI you could for instance swap two different implementations at run time, which is heavily used in testing.

In Universal, we take advantage of this DI system and provide you with many services that are specific to the targeted platform. For Node, we provide a custom ServerModule that implements Node’s server specific APIs such as requests rather than Browser’s XHR. Universal is also shipped with a custom renderer specific to Node, and of course we provide you with a bunch of prerenderers — as we call them — such as Express renderer or Webpack renderer for your Node backend technologies. For other non-JavaScript technologies, such as .NetCore or Java, you should expect other prerenderers as well.