Boost your Angular App using AppShell

Nikhil Walvekar
Technext
Published in
4 min readApr 17, 2019
Photo by Veri Ivanova on Unsplash

Here is the Tour of Heroes app, everyone has built this or similar app. A material toolbar is introduced on top of existing app.

Tour of Heroes app, built as part of Angular tutorial.

Everything looks fine, app is loaded, there is no lag.

Let’s play with network tab and simulate Fast 3G.

Same app with network throttle set to Fast 3G
Source: Zootopia

The app which was loading in ~1 secs took 2.2 secs.

The main culprit is the connection, which is slowing down all downloads. Once the required files are downloaded, browser starts rendering the contents.

Browser rendering is not that simple, there is lot more happening before browser starts to render the content.

How browser rendering works — behind the scenes
by Ohans Emmanuel , LogRocket

In old days with servlet/JSP/ASP based apps, index.html was returned with complete renderable HTML elements along with other information such as data, CSS, JS. There were no client side frameworks for dynamic rendering; browsers were able to render the contents directly.

Now with SPA, the index.html contains only container and everything is rendered dynamically. We see blank page till the framework (Angular) kicks-in and loads required component.

AppShell can help in this case

Here is side-by-side view of same app without and with AppShell with simulated Fast 3G speed. The app with AppShell shows some contents around 1.2 secs as compared to previous ~2.2sec

Side by side comparison of with out and with App shell.

What is AppShell?

An application shell (or app shell) architecture is one way to build a Progressive Web App that reliably and instantly loads on your users’ screens, similar to what you see in native applications. — Addy Osmani

Let’s keep PWA out of the definition.

App shell consists of skeleton of your app, it will render appropriate placeholder components. Those components may not contain data, but user will get idea that something will be rendered here. Rendering this skeleton helps us to improve perceived performance of the app.

In our sample app, App shell is the header with navigation links.

How do we create App shell with Angular?

Generate App shell

ng generate app-shell --client-project my-app --universal-project server-app
  • my-app is the name of your app
  • server-app is the name for your server (Universal) app.
    Is the name of the server-side app module to be generated.

Server-side Rendering (SSR): An intro to Angular Universal

Following changes are made to the project

  • Added AppShell component
  • AppServerModule & Main Server file
  • Angular.json has new configuration
    The above command will add configuration to your angular.json
"server": {
"builder": "@angular-devkit/build-angular:server",
"options": {
"outputPath": "dist/my-app-server",
"main": "src/main.server.ts",
"tsConfig": "tsconfig.server.json"
}
},
"app-shell": {
"builder": "@angular-devkit/build-angular:app-shell",
"options": {
"browserTarget": "my-app:build",
"serverTarget": "my-app:server",
"route": "shell"
}
}

Run the app

ng run my-app:app-shell

This will build the app and contents will be stored in dist folder. If you inspect dist/index.html you will notice app-root is not empty.

<app-root>app-shell works!</app-root>

The contents under app-root are important, now the index.html is served with these contents. These contents will be rendered till browser fetches & bootstraps Angular and in-turn Angular loads component.

Customizing App shell component

You can customize app shell component contents, by default it contents app-shell works!. You can modify, I have added a simple loader instead of the text.

A skeleton screen is also a good idea to have.

How it works?

When you add app-shell, it adds a target to angular.json to generate index.html using SSR. During build, server will render /shell route and generated HTML is copied to index.html.

This also means, if your AppComponent is using any other components those will also get rendered in index.html

Let’s analyze this file

  • App component uses Material Toolbar, which gets added to index.html
  • router-outlet is preserved as it is.
  • app-app-shell is the App shell component which was generated. It has Material spinner added, which is shown when the page loads. It embeds SVG inside it.

This index.html provides a app-shell (as mentioned in definition) skeleton of the app layout.

How to create production build?

ng run my-app:app-shell:production

Next steps

  • Use skeleton screen in App shell component instead of loader.
  • Try to build app shell just using HTML & CSS, browser can render these contents, without JavaScript.

Source code reference

Tour-of-Heroes app from Angular guide.
App without app shell
App with app shell

--

--

Nikhil Walvekar
Technext
Editor for

Full stack developer | Angular | JS | HTML | CSS | PWA | Java | NodeJS | Photographer