Disclaimer: This blog post will be a focused step-by-step tutorial of how to deploy an Angular Universal App using Firebase Hosting. For any explanations about Angular Universal and Server Side Rendering, Angular has a great documentation on their website.

You can also find the source code on Github.

Requirements

Part I: Set Up Angular App 🛠

1. Install global dependencies

We are going to use @angular/cli and firebase-tools in command line to build and deploy your app.

2. Create a new Angular project

Using @angular/cli , we are going to create a new angular app. In this case, I will name it angular-universal-firebase .

3. Install @angular/platform-server

To build and render your universal app, we need to install @angular/platform-server .

4. Add Server Side Rendering Config

In @angular/[email protected]+ , .angular-cli.json is changed to angular.json . This defines how our project is structured and the build configurations for this project. We would want to add a server configuration for the project in the projects.PROJECT_NAME.architect path.

Note that we’ve added server that defines the builder and options config for the server side version of our app.

5. Modify project output to Firebase folder

For simplicity, we will build the browser version of our app in the same directory as where we are building our sever version to be server side rendered in Firebase. To do this, edit angular.json ‘s PROJECT_NAME.architect.build.options.outputPath to functions/dist/browser.

6. Create necessary files for app server version

Create a new module for the app’s server version.

https://github.com/aaronte/angular-universal-firebase/blob/master/src/app/app.server.module.ts

Create an entry point for the server module. This is the main file we referenced in the server configuration in angular.json .

https://github.com/aaronte/angular-universal-firebase/blob/master/src/main-ssr.ts

Create the tsconfig for the server version. Similar to the browser version except angularCompilerOptions.entryModule which will reference the entry module for the server version that we just created. This is also referenced in angular.json as tsConfig.

https://github.com/aaronte/angular-universal-firebase/blob/master/src/tsconfig.app-ssr.json

7. Include server transition in app’s browser module

Since we are sending the server version of your app to the browser before the browser version, we need to add .withServerTransition({ appId }) when adding BrowserModule in imports.

https://github.com/aaronte/angular-universal-firebase/blob/master/src/app/app.module.ts

Now we are ready to build the server and browser versions of our app!

8. Build browser and server versions of the app

Using @angular/cli, we will build the two versions of the app.

When both builds are done, you should now have a functions folder in your root directory with browser and server folders in it. Awesome!!! 🎉

Part II: Deploying with Firebase 🚀

[1] Before continuing, you should have had created a firebase project here. I named mine _angular-universal-firebase_ for this case.

1. Log in to `firebase` in the command line

Log in to firebase in the command line with the same google account you used to create your firebase project in [1].

2. Initialize Firebase in the `angular` project

Initialize firebase configurations through the command line:

Firebase set up configuration (Functions and Hosting)

Javascript as Cloud function language for simplicity

3. Add package dependencies to `functions`

Since we are using a node server through firebase-functions, We need to include angular dependencies in functions/package.json to render the server version of the app.

Aside: Right now, I don’t know any way to mitigate this duplication of dependency declaration since as far as I know, you can’t access files outside the _functions_ directory in any _firebase-functions_ javascript files. But if you know a way, please let me know!

https://github.com/aaronte/angular-universal-firebase/blob/master/functions/package.json

4. Install packages in `functions` directory

Install da dependencies!

5. Create Firebase function to serve the app

We are going to use functions.https.onRequest Firebase function type to send the response from our express server. There are a lot of things going on in this file but the most notable are:

https://github.com/aaronte/angular-universal-firebase/blob/master/functions/index.js

7. Configure Firebase hosting

Now that we have built the function to render pages, we need to change the firebase hosting configuration to use this function. Change the hosting.rewrites in firebase.json. The first entry is to send static files (css and js) through our public folder. The second entry is to direct all requests to the ssr function.

https://github.com/aaronte/angular-universal-firebase/blob/master/firebase.json

8. Copy all content of `functions/dist/browser` to `public`

Since we want to run our application like a normal application, we want to put all the files generated by building our platform for the browser in the public folder. This means the html, js, css, etc in the functions/dist/browser should all be present in the public folder. Note: We have to, however, change the name of index.html to index2.html because firebase won’t run the ssr function if it finds index.html in the public folder.

9. Deploy to Firebase 🚀 🔥

If all things went well, you should be able to deploy your app to Firebase:

That’s it! 👍

You can check out the source code on Github.

I hope this tutorial was helpful in some way! If you have any feedback or questions, add them on the Github issues to ensure everyone looking at the code would benefit. 😄

Happy coding! 😃