As of writing the latest version is 2.1.0-RC.1, which introduced ahead of time compilation (AoT) support. What is angular2-universal? First, a bit of history regarding AngularJS. Version 1 of angular was very tightly coupled with the . That means that any application you write has to be run in the browser or at least some sort of browser emulator. DOM The inability to run angular in any was one of the driving forces for the complete rewrite of the angular code base. They wanted to abstract away access to the DOM and in doing so, they opened up the possibility of running angular2 within a service worker, a node server or ever a .NET server. The shackles have been broken. environment A very awesome developer, from , stepped up to the plate and created , which is the middleware that sits between the node server and angular2. PatrickJS AngularClass angular2-universal Why should I care? One of the main selling points of server-side rendering is the SEO value it brings. Even though googlebot is indexing single page applications, so it’s less of a concern now-a-days, I have a different . There are still other search engines to consider as well as rich media sharing on social media sites like facebook and twitter. post about that Another great selling point is the increased perceived performance. Since the server is sending the fully rendered html page over the wire the user sees the content and is able to interact with it much faster. Couple that with a CDN for static pages and the origin server barely gets hit, which brings down the cost of running servers. Setting up the front-end There are a few gotchas with angular2-universal and just general best practices when it comes to angular2. The main one is, don’t access the DOM directly. Any direct references to or in your code will cause universal to crash or at best throw errors at you. Neither of those objects exist on node, so don’t try to use them. document window However… There are certain libraries that access the DOM and they can’t be avoided in some cases. One very popular example is hammer.js, a touch events library. Angular2 supports this library in it’s core with , which is essentially an extension of angular’s event binding system. Including hammer.js does not actually crash anything, it’s once you bind a touch event to an element that it actually crashes. HammerGesturePlugin <div (swipe)=”myAction()” /> // Bound touch event Here’s the very hacky work around that PatrickJS and I came up with. There’s no promise that this will work with future releases of either angular2 or angular universal. import { __platform_browser_private__ } from ‘ ’; @angular/platform-browser __platform_browser_private__.HammerGesturesPlugin.prototype.supports = function hackySupports(eventName: string): boolean {if (!this.isCustomEvent(eventName)) {return false;}return true;}; If you absolutely have to have a reference to or in your code the you would have to like wrap that code in an conditional, which can conveniently be imported from . document window isBrowser angular2-universal import { isBrowser } from ‘angular2-universal’; … if (isBrowser) {// Do the thing} Alternatively you can provide at the root level, , and then inject it as a dependency into your components, directives, pipes and services as needed. isBrowser app.module // app.module.tsimport { NgModule } from ‘ ’;import { isBrowser } from ‘angular2-universal’; @angular/core ({providers: [{ provide: ‘isBrowser’, useValue: isBrowser }]}) @NgModule // my.component.tsimport { Component, Inject } from ‘ ’; @angular/core ({…})export class MyComponent {constructor( (‘isBrowser’) public isBrowser: boolean) { }} @Component @Inject The main thing to take into account is that has it’s own module, . This needs to be imported at the root level or imported and then exported from the shared.module. angular2-universal UniversalModule There are technically 2 versions of this module. One that’s imported from and one that’s imported from . You’ll have to create 2 different entry files, and , respectively. angular2-universal/browser angular2-universal/node app.module app.module.browers.ts app.module.node.ts // app.module.browers.tsimport { NgModule } from ‘ ’;import { UniversalModule } from ‘angular2-universal/browser’; @angular/core ({import: [UniversalModule]}) @NgModule The node version of that file is exactly the same except that is replace with . angular2-universal/browser angular2-universal/node already exports , and . So those can safely be removed the imports. UniversalModule JsonpModule HttpModule BrowserModule app.module Setting up the back-end In order for to work with express the package needs to be installed. This is the middleware that sits between universal and express. angular2-universal angular2-express-engine The route which serves the bare file is no longer needed and can be removed from the server config. The other routes, like assets, can be kept intact. Here is a basic skeleton of what the server file looks like, it’ll all be explained below. html import { createEngine } from ‘angular2-express-engine’;import { AppModule } from ‘./app/app.module.node’; // Express Viewapp.engine(‘.html’, createEngine({ngModule: AppModule,precompile: true})); app.set(‘views’, ‘./dist/client’);app.set(‘view engine’, ‘html’); app.use(‘/*’, (req, res) => {res.render(‘index’, {req,res,preboot: false,baseUrl: ‘/’,requestUrl: req.originalUrl});}); There are a few key things that are going on here. First, the render engine needs to be set, that’s the part. takes in an object with 2 keys, and . The former is the node version of the and the later is a flag that tells universal if the application is in just in time or ahead of time compilation mode. Setting to means that the application is using just in time. app.engine createEngine ngModule precompile app.module precompile true The with as the first parameter In order for universal to bootstrap and render each route of the application app.use ’/*’ Then you need to make sure that express actually serves up the prerendered pages for all your routes. Make sure to add this below any other routes that you have defined in express. If you don’t, these routes will take precedent and overwrite the ones below it. Conclusion That just about covers the basics of setting up universal on a node/express server. There are a few things that I didn’t go over in this post like setting up a cache between the server and client. If your app depends on xhr requests then both the server and client will be making those requests on page load and refresh. This can be avoided by caching the response from the server and reading it on the client side. The other pain point is setting up ahead of time compilation with universal. That’s a whole different post altogether, which is next on my Bee Todo List is how hackers start their afternoons. We’re a part of the family. We are now and happy to opportunities. Hacker Noon @AMI accepting submissions discuss advertising &sponsorship To learn more, , , or simply, read our about page like/message us on Facebook tweet/DM @HackerNoon. If you enjoyed this story, we recommend reading our and . Until next time, don’t take the realities of the world for granted! latest tech stories trending tech stories