Angular Tutorial: Server Side Rendering

How do you go from a normal app to a server-rendered app? Let’s start with a normal app. Download  Tour of Heroes. This is the completed tutorial app they use over at angular.io.

Once downloaded, head over to the root of the app and  npm i  to install the dependencies. Then do  npm start and head over to  http://localhost:4200  to check the app working. You should see something like:

Tour of Heroes main page

When you first go into the page, there is nothing. the HTML the server sends doesnt have anything in the body more than the script files. The browser has to first get the scripts and execute them before we can see something. This is how SPAs (Single Page Application) work.

With SSR (Server Side Rendering) we can change that so that when we navigate to a page, we get pre-rendered HTML like we did in the pre SPA days

To get this in Angular you do:

ng add @nguniversal/express-engine --clientProject angular-io-example

This modifies your app to support Server Side Rendering. It also generates files that are now needed for it to work. You should see the terminal output the new files generated and the ones modified in your project:

The generated and updated files

Note: If you don’t see new the new files, bump up the TypeScript version to something like 3.2 and try again. Happened to me and found the answer in stack overflow. If you still can’t run the app, use my version.

That’s it. Now your app supports SSR. Don’t believe me? Run the following:

That will build the app and start a node server on  http://localhost:4000. Head over there to see for yourself. Check that you are on port 4000 and not 4200.

Note: You can still run the app in its normal non-SSR mode whenever you want with  npm start

Proof that it Works

When you open the server rendered version you can check it works by heading over to the network tab in the chrome inspector. Take a look at the first document the browser receives, it’s always the HTML. Inside you will see there’s a bunch of content inside the body tag.

This means the browser does not have to wait for the Javascript to execute to paint something in the screen. It can do that immediately by parsing the HTML thanks to having stuff rendered in the server.

In the network tab, the first file to download is the document. This brings the HTML for the page. We can see that in the preview we already have a lot of elements ready to be rendered by the browser. No need to wait for the JS

If you were to run the normal app without SSR again. You could again check the network tab and inspect the document, you will see nothing in the preview since there is no pre-rendered content coming in from the server. Everything has to be built by the browser when it executes the Javascript.

A blank preview. Nothing inside the body tag since there’s no SSR

Limitations of Server Side Rendering

Server Rendering has its limitations. If you slow down the speed, you will notice that some functionality of the app is not working, even if a lot has already been painted to the browser. This is because it needs to wait for the Javascript to load to have full functionality. Some things work right away though, like navigation.

Navigation works right away because if the Javascript hasn’t loaded and a user clicks a link, that request is sent back to the server where it is handled. Once the Javascript is loaded, however, the navigation is handled by the browser with the use of Angular’s router. It’s quite awesome really, the user doesn’t perceive who’s handling the navigation or when the change of navigation ownership happens, it just works.

The few milliseconds you are left with only navigation capabilities is something you should take into consideration when developing with SSR. Do you want users to be able to do something right away when a component loads? Maybe you should put a loader on that component, so the users know that part is still loading. You can take off the loader once angular has been bootstrapped.

You can also use preboot to capture any actions the user has taken before the app fully loads and replay them.

Generated files: In-depth

Let’s go through the generated files and what they do.

main.server.ts

This is the bootstrapper for the server app. It exports the AppServerModule . 

app.server.module.ts

This is the main module when using server side rendering. It imports the AppModule , which contains all the app’s logic. This is good, the app shouldn’t know if it’s going to be server rendered or not.

Then we import the ServerModule  from the @angular/platform-server  package. This module probably has code that supports running Angular on the server, just like  BrowserModule gives Angular support on the browser.

Lastly we import  ModuleMapLoaderModule which comes from the universal package. This is used to load the modules instantly instead of lazily, we dont need lazy loading when loading modules in the server.

tsconfig.server.json

Pretty self-explanatory. It’s the compile config for TypeScript in the server. It actually extends the tsconfig.app.json file.

webpack.server.config.js

Webpack server configuration. This tells Webpack to compile the server server.ts (which is in TypeScript) and output in the dist folder.

server.ts

Our node express server. This server handles requests to the app, builds what it can on the server (SSR), and sends it to the browser.

How does it all tie in together?

So we saw the generated files and know what they do. Now we can look at how it all ties in together, the workings of this new app.

Build and Run

First of all, let’s go back to these commands:

It builds the app in SSR mode and runs a server to support it. Let’s look at the first command  build:ssr . This is an npm command which was generated when we made the app support Server Side Rendering. You can find it in the package.json. It does this:

The first command  build:client-and-server-bundles  will do the builds for both the app and server bundles:

As you can see, it boils down to using angular-cli to build the prod version of the app and also this  angular.io-example:server:production , which builds the server bundle. For the client app, the main.ts file is used as entry point. For the server, it’s main.server.ts

The second command   compile:server will compile the server with a direct command to Webpack. Since this is outside Angular, we can’t use the angular-cli. Also, we need to run this because the server source file is in TypeScript, so it needs to be compiled and sent to the dist folder from where it will be run.

Let’s go back to the original commands and see the second command  npm run serve:ssr . If we check the package.json we see this refers to this command:  node dist/server . It starts a node server file located in dist/server, which is the compiled version of the server.ts file from before.

The last part is important. We now have a server. Whereas before we didn’t need one, now we do, and we can’t have SSR without it. Think about this when you design the architecture where your app will run. You could have a node express server running to handle page requests, and have another one in any tech you want that handles data requests.  Or you can use the node server as a proxy between your app and your data server too, or just have everything in node. Up to you!

Flow

We know how the app is built and run now. Let’s look at how it flows.

It all starts with navigating to the app. Upon entering a URL, say the default page, the request for that page is sent to the server. This is where server.ts comes in.

The first relevant code line we find in the server.ts is

We are importing the server module, the one we export in main.server.ts. Remember this one has the three imports we discussed earlier: AppModule, ServerModule, ModuleMapLoaderModule.

After that we have this piece of code:

We are telling express that we will use the ngExpressEngine as the HTML engine, a handy tool to abstract Server Side Rendering stuff. We pass in the server module containing everything needed to run the app, and also the lazy module map to load modules instantly.

So when a request comes in, this is the part being fired:

the HTML engine we configured earlier will take care of handling the request by compiling angular and spitting out the HTML to the browser.

Once in the browser, the flow of the app is the same as a non-SSR app, with the exception that now the page renders faster.

 

 

 

 

Webpack for connected set ups

For a long time, I had the notion that webpack could only be ran for set ups that are independent from the back end. For example SPAs that only communicate with AJAX.

I closed my mind into thinking that it had to be ran with a development server. You would make the webpack config file and use that to run the dev server. That would do all the cool things like Hot Module Replacement and having all the JS in RAM so changes would be blazing fast. Then, when you needed to actually use it for production, you would do a build and be done with it.

I blame the tutorials and webpack docs partly, because when I started looking into webpack around 2 years ago all the examples where like what I mentioned before, independent set ups.

So the only time I used webpack was for personal projects. But on my professional projects I would use gulp with require/browserify/jspm whatever was in flavor besides webpack. Until I came across a project that used it the way I wanted to.

You can use webpack to develop in a set up where you have the back end connected with the front, for example with a templating language. All you need to do is define an input file and output directory in your webpack config. Then you run webpack -w and that’s it. It will watch for changes, and then do what it does, and throw it to the output directory you specified. After that, you just point to the output file in your template like <script src="./build/index.js" />. This project does just that, as simple as possible.

You won’t benefit from HMR, but at least you CAN use webpack for these connected set ups which are much more common in the professional world.

Webpack can be simple too.

Example

I went ahead and created a very simple example for you. Click here to download it through github.

Install dependencies:

run webpack:

this will bundle what’s in the entry file and its imports and output it in the /build directory.

Check out the changes by navigating to the index.html file, or start a server in the project’s root directory with:

Some info on the project

The javascript is simple, it just imports a module and calls it. This is to demonstrate what the core of webpack is all about: bundling.

So to get that code above to work, webpack needs to be set up:

This is all webpack needs to do its job. An entry place to your app, and where to output the generated bundle. That’s it.

All the other stuff, loaders, plugins, etc. are to enhance webpack, and accommodate to your needs of using babel, SASS, css modules, etc…

Boilerplate: Webpack + React + Redux

A boilerplate for playing around with react, redux and react-router with the help of webpack.

Contains:

  • a working example of a filterable table which you can play around with (look below).
  • ES6 – 7 Support with Babel
  • Redux dev tools to help you keep track of the app’s state
  • hot module replacement support so you can change modules or react components without having to reload the browser
  • a webpack production config so you can build the app and make it ready for production
  • Sass support, just import your styles wherever you need them
  • eslint to keep your js readable
  • much more…

Run the app

  1. npm install
  2. npm start

Once running, if you want to hide the redux dev monitor: CTRL+H

Yes, it takes a while to load the first time you open the app.

Is the hot module replacement really working?

Yup! Take a look:

The app updates without the browser having to reload. You don’t lose state!

Build the app

npm run build

This will build the app into the “dist” directory in the root of the project. It contains the index.html along with the minified assets, ready for production.

It should look something like the above image.

I don’t understand anything!

I went ahead and wrote a detailed series of posts on this project for you. I hope it helps you understand better:

Why doesn’t it have async?

To keep it unopinionated. You choose what async library you want. If you want to check out a full example with async in it, check this simple todo-app

Understanding a Simple React, React-Router and Redux Application in ES2015. Part 2

This is the third article in a series of posts on react, redux and webpack. Others:

  1. configuring webpack
  2. Understanding a simple react, redux and react-router app in es2015, part1.

Here, we will cover the routes configuration, the actions and all the react components starting from the Root.

Continue reading “Understanding a Simple React, React-Router and Redux Application in ES2015. Part 2”