Developers use JavaScript frameworks like Angular, React, and Vue.js to build every kind of single page application, from simple to complex. By separating JavaScript and CSS, frameworks let dev teams structure applications in modular chunks of code that carry out a single function.

That is great, but once your application is ready for deployment to production, you will need a command to compile and bundle the separate files into a single one. Then you will need to deploy to a platform like Firebase hosting.

Firebase is a development platform developed by Google that provides file storage, hosting, database, authentication, and analytics. Firebase is free, provides an SSL certificate by default, and offers impressive speed across multiple regions.

In this tutorial, I will show you how to set up continuous deployment for an Angular application to Firebase hosting.

Prerequisites

For this tutorial, you will need:

Cloning the demo Angular project

To get started, run this command:

git clone https://github.com/CIRCLECI-GWP/automate-angular-firebase-app.git angular-ci-firebase

Git will clone the demo application into a new folder named angular-ci-firebase. Move into the newly cloned app and install all its dependencies:

// Change directory
cd angular-ci-firebase

// Install dependencies
npm install

// Run the application
ng serve

Open the application by going to http://localhost:4200.

View demo app

This application retrieves the list of dummy users from a free Rest API for testing.

Testing your Angular app locally

Run the test for the application with:

npm run test

The following output will be something like this:

> automate-angular-firebase-app@0.0.0 test
> ng test --no-watch --no-progress --browsers=ChromeHeadless

18 06 2023 17:57:22.965:INFO [karma-server]: Karma v6.4.2 server started at http://localhost:9876/
18 06 2023 17:57:22.967:INFO [launcher]: Launching browsers ChromeHeadless with concurrency unlimited
18 06 2023 17:57:22.968:INFO [launcher]: Starting browser ChromeHeadless
18 06 2023 17:57:23.275:INFO [Chrome Headless 114.0.5735.133 (Mac OS 10.15.7)]: Connected on socket O3b2eDIPMJY9kBIAAAAB with id 11144817
Chrome Headless 114.0.5735.133 (Mac OS 10.15.7): Executed 4 of 4 SUCCESS (0.046 secs / 0.03 secs)
TOTAL: 4 SUCCESS

The demo application is now set up locally and working perfectly.

Creating a project on Firebase

If you have not yet done so, open up a Firebase account, navigate to the Firebase homepage and click Create A Project.

Firebase Console page

Next, use the following steps:

  1. Click the Add project button.
  2. Enter a name for your project. I have named mine angular-circle-ci-project. Keep in mind that project IDs are unique in Firebase.
  3. Click Continue.
  4. Disable Google Analytics; it is not required for this project.
  5. Click Continue again.

Firebase app setup

There you have it. You have successfully created a project on Firebase.

Setting up Firebase hosting

To successfully host your application on Firebase, you need to install its tools and initialize it within your project.

Install the Firebase CLI

Open a new terminal. To install Firebase tools globally, run this command:

npm install -g firebase-tools

You now have global access to Firebase Command Line interface tools. You can use them to deploy code and assets to your newly created Firebase project.

Initializing a Firebase project

From the terminal, sign in to your Firebase account:

firebase login

Next, initialize the project:

firebase init

You will be prompted to respond to some questions.

  • Choose hosting: Configure files for Firebase Hosting and (optionally) set up GitHub Action deploys.
  • Use an existing project: Select the Firebase project you created earlier: angular-circle-ci-project.
  • Enter dist/angular-circle-ci-project as the public directory. Note that angular-circle-ci-project is the name of the folder for the project. Change this if yours is different.
  • Configure as a single-page app: Yes.
  • Set up automatic builds and deploys with GitHub: No. For this tutorial we are using CircleCI to run tests and handle deployment.

Here is the output and screenshot of the steps.


     ######## #### ########  ######## ########     ###     ######  ########
     ##        ##  ##     ## ##       ##     ##  ##   ##  ##       ##
     ######    ##  ########  ######   ########  #########  ######  ######
     ##        ##  ##    ##  ##       ##     ## ##     ##       ## ##
     ##       #### ##     ## ######## ########  ##     ##  ######  ########

You're about to initialize a Firebase project in this directory:

  /Users/yemiwebby/automate-angular-firebase-app

? Which Firebase features do you want to set up for this directory? Press Space to select features, then Enter to confirm your choices. Hosting: Configure files for
Firebase Hosting and (optionally) set up GitHub Action deploys

=== Project Setup

First, let's associate this project directory with a Firebase project.
You can create multiple project aliases by running firebase use --add,
but for now we'll just set up a default project.

? Please select an option: Use an existing project
? Select a default Firebase project for this directory: angular-circle-ci-project (angular-circle-ci-project)
i  Using project angular-circle-ci-project (angular-circle-ci-project)

=== Hosting Setup

Your public directory is the folder (relative to your project directory) that
will contain Hosting assets to be uploaded with firebase deploy. If you
have a build process for your assets, use your build's output directory.

? What do you want to use as your public directory? dist/angular-circle-ci-project
? Configure as a single-page app (rewrite all urls to /index.html)? Yes
? Set up automatic builds and deploys with GitHub? No
✔  Wrote dist/angular-circle-ci-project/index.html

i  Writing configuration info to firebase.json...
i  Writing project information to .firebaserc...

✔  Firebase initialization complete!

Firebase initialized

The project’s initialization process also generated two unique files at the root of your project. These files are required for successful deployment and must be checked into source control. They are:

  • firebase.json contains your project’s hosting configuration. Its content instructs Firebase CLI about the files in your project directory to upload and deploy.
  • .firebaserc specifies the project to connect to the uploaded code once you successfully deploy to Firebase.

Changing the output path

Once you are ready to build your production application, the Angular CLI will compile it into an output path specified in the angular.json file. Open this file and make sure that the outputPath points to dist/angular-circle-ci-project:

 "build": {
          "builder": "@angular-devkit/build-angular:browser",
          "options": {
            "outputPath": "dist/angular-circle-ci-project",
            "index": "src/index.html",
            "main": "src/main.ts",
            "polyfills": "src/polyfills.ts",
            "tsConfig": "tsconfig.app.json",
            "assets": ["src/favicon.ico", "src/assets"],
            "styles": [
              "./node_modules/bootstrap/dist/css/bootstrap.css",
              "src/styles.css"
            ],
            "scripts": []
          },

Configuring CircleCI to deploy your Angular app to Firebase

Next, replace the content of .circleci/config.yml with this:

version: 2.1
orbs:
  browser-tools: circleci/browser-tools@1.4.1
jobs:
  build:
    working_directory: ~/ng-project
    docker:
      - image: cimg/node:lts-browsers
    steps:
      - browser-tools/install-chrome
      - browser-tools/install-chromedriver
      - run:
          command: |
            google-chrome --version
            chromedriver --version
          name: Check install
      - checkout
      - restore_cache:
          key: ng-project-{{ .Branch }}-{{ checksum "package-lock.json" }}
      - run: npm install
      - run: npm install --save-dev firebase-tools
      - save_cache:
          key: ng-project-{{ .Branch }}-{{ checksum "package-lock.json" }}
          paths:
            - "node_modules"
      - run:
          name: "Run test"
          command: npm run test
      - run:
          name: "Build application for production"
          command: npm run build
      - run:
          name: "Generate Service Account Authentication"
          command: 'echo "$GOOGLE_APPLICATION_CREDENTIALS_BASE_64" | base64 --decode > $GOOGLE_APPLICATION_CREDENTIALS'
      - run:
          name: "Deploy app to Firebase Hosting"
          command: "./node_modules/.bin/firebase deploy --non-interactive"
      - run:
          name: "Remove credentials file"
          command: "rm $GOOGLE_APPLICATION_CREDENTIALS"

This configuration specifies all the required tools to install and run the test for your application on CircleCI. The config installs the Firebase tool with npm install --save-dev firebase-tools and sets up a command to automatically deploy your application to Firebase once the tests are successful.

Deployment to Firebase requires authentication from a service account with appropriate privileges on the project. The credentials required for this authentication are provided in a JSON file - the name of which is saved in the GOOGLE_APPLICATION_CREDENTIALS variable.

To get this JSON file, open your Firebase project console and select the Service accounts tab. Click the Generate new private key button to download the JSON file.

Generate new private key

NOTE: This key is used for demonstration purposes. Using the default service account is not recommended, because by default the default service account is highly privileged, which violates the principle of least privilege.

The JSON file you just downloaded will need to be base64 encoded to get the string value of GOOGLE_APPLICATION_CREDENTIALS_BASE_64. Do this with the following command.

base64 -i <</path/to/json/file>>

Replace <</path/to/json/file>> with the path to the JSON file you downloaded earlier.

Encode credential

Copy the output of the command and save it somewhere convenient. You will need it later on CircleCI.

When CircleCI is deploying your application to Firebase, the GOOGLE_APPLICATION_CREDENTIALS_BASE_64 variable will be decoded to a file whose name is the value of GOOGLE_APPLICATION_CREDENTIALS. This file will then be used by Firebase to authenticate and deploy the changes.

The next step is to set up a repository on GitHub and link the project to CircleCI. Review Pushing a project to GitHub for instructions.

Log in to your CircleCI account. If you signed up with your GitHub account, all your repositories will be available on your project’s dashboard.

Next to your angular-circle-ci-project project, click Set Up Project.

Set up project

You will be prompted to either write a new configuration file or use the existing one. Select the existing one and enter the name of the branch where your code is housed on GitHub. Click Let’s Go.

Configuration File

Your first workflow will start running, but as expected, the build will fail because you have not yet created the GOOGLE_APPLICATION_CREDENTIALS_BASE_64 and GOOGLE_APPLICATION_CREDENTIALS environment variables.

To add them, click Project Settings.

Project settings

Click Environment Variables on the left sidebar and create this variable:

  • GOOGLE_APPLICATION_CREDENTIALS_BASE_64 is the value of the base64 encoded JSON you generated from the terminal earlier.
  • GOOGLE_APPLICATION_CREDENTIALS is the name of your credentials file for example credentials.json. Ensure that whatever name you choose has the .json extension.

Add Credentials ENV

Go back to the dashboard. Click Rerun Workflow from Failed.

Your build should finish successfully!

Hosted successfully

Navigate to the hosting URL shown in the last step. For me the URL is: https://angular-circle-ci-project.web.app.

Live Firebase app

Conclusion

You have reached the end of this Angular to Firebase deployment tutorial. With the Firebase tools installed locally on your system, you could just deploy to Firebase directly, but that defeats the purpose of continuous integration and continuous deployment (CI/CD). The ideal approach is to run tests using a platform like CircleCI, then once the tests pass, deploy immediately to your hosting provider, Firebase in this case.

With what you have learned in this tutorial, you can easily run tests and deploy your application every time you make changes to your codebase.

I hope that you found this helpful. The complete source code for this tutorial can be found here on GitHub.


Oluyemi is a tech enthusiast with a background in Telecommunication Engineering. With a keen interest in solving day-to-day problems encountered by users, he ventured into programming and has since directed his problem solving skills at building software for both web and mobile. A full stack software engineer with a passion for sharing knowledge, Oluyemi has published a good number of technical articles and blog posts on several blogs around the world. Being tech savvy, his hobbies include trying out new programming languages and frameworks.

Read more posts by Olususi Oluyemi