Angular Universal Applications

Angular Universal Applications are the key … why?

As you all may already know Angular is already widely used in a lot of applications (both static and dynamic apps or web pages).

But as any SPA technology (Single Page Application), It may be the worst for SEO, because SPAs basically rely on rendering pages on the browser using JavaScript, and according to this it will be bad for Search Engines to index and know any content about those pages.

Why .. ?

Because simply … Search Engines don’t run javascript, they just crawl and scrap the returned text/content from servers, and they just won’t run any javascript on that page.

Running no javascript means no content for any website that uses an SPA technology.

How do we overcome this? … yes? SSR (Server Side Rendering) !!

Of course, the default scaffolding template for Angular CLI is based on Client Rendering (AKA Javascript will run on the browser and will keep on adding content as you keep surfing pages)

That’s the initial HTML:

<!DOCTYPE html>
<html>
    <head>
        <script src="main.js"></script>
    </head>
    <body>
        <app-root></app-root>
    </body>
</html>

The main.js file will run its content and will replace <app-root></app-root> with the corresponding component (Which is the bootstrap component and Angular will go on from here) all that will happen on the browser. Looking at the above code, that’s the content which will be fetched by Search Engines, just a single tag with no info or content or meta tags or anything that describes the website … HOW ON EARTH CAN SEARCH ENGINES index that site???

huh ?

We gotta use Server Side Rendering … or … yes .. Angular Universal Applications

To do so, you will need to convert your app to a Universal App, so how can we do this?

There’s a command from Angular/CLI that does so which is

ng add @nguniversal/express-engine

// To Serve you need to run:
npm run dev:ssr

// To build you need to run:
npm run build:ssr

The difference in serving your apps when you use CSR (Client Side Rendering) and SSR is:

  • When you use CSR you basically run ng build and you should have a dist folder that contains an index.html file and you point your server (ie: nginx) to serve that index.html and then all the magic happens 🪄🔮
  • When you use SSR you will need to run npm run build:ssr which will create a dist folder which contains two folders browser and server , the server folder contains a file named main.js , you should use NodeJS to turn that script using node dist/server/main.js which will run an ExpressJS Server serving that index.html file in the browser folder.
    • The nodejs server will be running on, let’s say … port 4200, so you will need to point your server (ie: nginx) to proxy to the nodejs server https://localhost:4200/
location / {
    proxy_set_header Accept-Encoding "";
    proxy_pass https://localhost:4200;
}

In Chrome, when you press ctrl+U it will show you the original source code for your index.html file, let’s see the difference between CSR and SSR on a brand new Angular application

CSR:


<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <title>MyNewAngularApp</title>
  <base href="/">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <link rel="icon" type="image/x-icon" href="favicon.ico">
<link rel="stylesheet" href="styles.css"></head>
<body>
  <app-root></app-root>
<script src="runtime.js" type="module"></script><script src="polyfills.js" type="module"></script><script src="styles.js" defer></script><script src="vendor.js" type="module"></script><script src="main.js" type="module"></script></body>
</html>

SSR:


<!DOCTYPE html><html lang="en"><head>
  <meta charset="utf-8">
  <title>MyNewAngularApp</title>
  <base href="/">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <link rel="icon" type="image/x-icon" href="favicon.ico">
<link rel="stylesheet" href="styles.css" media="print" onload="this.media='all'"><noscript><link rel="stylesheet" href="styles.css"></noscript><style ng-transition="serverApp">
/*# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IiIsInNvdXJjZVJvb3QiOiIifQ== */</style></head>
<body>

  <app-root _nghost-sc1="" ng-version="15.2.9" ng-server-context="ssr">
       <h1 _ngcontent-sc1="">
            MyNewAngularApp
       </h1>
</app-root>
<script src="runtime.js" type="module"></script><script src="polyfills.js" type="module"></script><script src="vendor.js" type="module"></script><script src="main.js" type="module"></script>

</body></html>

Notice: that it added the Application Title (MyNewAngularApp) in the page source, so that will allow search engines to read the content of the website and show better results indeed.

In the coming post, we will talk about how to use SSR with SEO and adding meta tags, as well as how to differentiate between http requests on the client vs calling http requests on the server.

If that post wasn’t so beneficial to you, here’s an Angular Potato … or go to https://josepham.me/ maybe you will find something useful there 🤔

Angular Universal Applications potato