Angular 5 universal with Transfer State using @angular/cli

Inspired from a question from @cooooool143: https://medium.com/@cooooool143/great-explanation-thanks-now-i-know-the-difference-494cc4de2b29

I’ll show you how to setup a universal project using Angular 5, currently in version: 5.0.0-rc.1.

This app will transfer it’s state from the server to the browser, to remove the need for a redundant HTTP request to fetch data again in the browser.

Lets get started, running the following commands:

npm install -g @angular/cli
ng new --skip-install universal-demo-v5
cd universal-demo-v5
code . # Open VSCode

Update our package.json dependencies and developer dependencies:

Now lets setup our Server Module

npm install -S @angular/platform-server@^5 express 
npm install -D ts-loader@^3 webpack-node-externals npm-run-all
npm install

Create a file in this path: src/app/app.server.module.ts

Update src/app/app.module.ts

We need to create a main file on this path src/main.server.ts to export our server module

Now lets update our @angular/cli configuration on .angular-cli.json

We need to create a new tsconfig.json file for the server, on this path: src/tsconfig.server.json

We need to update this file src/tsconfig.app.json

Now run the following commands, to see if it builds correctly:

ng build -prod --build-optimizer --app 0
ng build --aot --app 1

After running both commands you should see the following output:

Now lets setup our Express.js server, you need to create this file: src/server.ts

We will need a webpack config file, just to build this server.ts file: webpack.config.js

Now we can add some scripts to our package.json file, to build our project.

Now you can try it out, just by running:

npm run build

You should see the following output:

Now to try it out on your browser, just run: node dist/server.js

Open http://localhost:4200/ and you should see your app working like the image bellow:

You will see on your developer tools, on the Network tab, inspecting the localhost request, that the content on the page comes rendered from the server.

Now lets talk about State, we are going to request some data, from some free REST API on our AppComponent.

Lets import the HttpClientModule on our AppModule:

Lets request some data:

Now lets show the data on our component template:

Lets see what happens running: npm run build && node dist/server.js

See that the HTTP request fetching data happens twice, one time on the server and one time on the browser, this is not a good idea.

We can solve this problem using the new Angular Modules for Transfer State, lets see how to use them.

Now we just need to make a small adjust on the main.ts file, to bootstrap our application only when the document is ready, for TransferState to work correctly:

Lets see what happens now running: npm run build && node dist/server.js

Now you can see that no extra HTTP request has been made on the browser, because the state have been transferred from the server to the client, in a new script tag with id=universal-demo-v5-state

If you face any issue, get in touch, here is my Github repo, you can clone it and try it out any time.

Any feedback or questions are really appreciated