DEV Community

Eduard Krivanek
Eduard Krivanek

Posted on

Setup Angular, Firebase Functions and Shared TS types in NX Monorepo

Recently I started to work on a new project and after a considerable amount of time spent choosing the tech stack, I decided to go with Angular, Firebase Cloud Functions, and NX Monorepo.

I want to share how I integrated Firebase Cloud Functions into an NX Monorepo and shared TS types between them because It took me a while to figure it out, so I hope it may help somebody.

Setup Project in Firebase

I won’t go into detail about how to set up a project in Firebase, it is a straightforward process that you can google, however, what I will include is that you will want to export your private key from Firebase to access your database

Image description

Add Firebase to an NX project

If you don’t have an NX project, follow its documentation on how to create one, however just by running nx g @nx/angular:application test-app it will create a Monorepo for you.

Once an NX app is generated you want to install the following package:

npm install -g firebase-tools

Which is a tool that can be used to test, manage, and deploy your Firebase project from the command line - link to NPM.

Install Angular/Fire

To enable the interaction between our Angular application and Firebase, you want to install @angular/fire. Using NX, you have to specify which application you want to target to communicate with Firebase, so the end command will be similar to:

nx g @angular/fire:ng-add --project=test-app
Enter fullscreen mode Exit fullscreen mode

Angular/Fire Problem with Standalone Project

If you are using standalone components in Angular, you most likely don’t have a app.module.ts file. In this case, the above command will fail with the message:

Image description

My workout was to create an empty app.module.ts file as follows:

Image description

Once this is done and you run the @angular/fire command again, it will output a successful initialization message:

Image description

Then you can copy the generated providers from app.module.ts into apps/test-app/src/app/app.config.ts as follows:

Image description

Adding Firebase Cloud Functions

This is a section where things started to get a bit complicated. There is no clear guideline from NX or Firebase on how to integrate cloud functions together. However, I was able to nx-firebase repo on Github, and by following its docs the integration is not that complicated so let’s take a look.

Head over to quick-start and install the package npm install @simondotm/nx-firebase.

Then run the following command to generate a new application only for cloud functions:

nx g @simondotm/nx-firebase:app test-app-functions
Enter fullscreen mode Exit fullscreen mode

Which will generate the below folder structure:

Image description

Missing @nx/node

I the process of adding cloud function I encountered the error of missing @nx/node, so I went to the NX docs website and manually installed npm install -D @nx/node the library.

Cloud functions - Sharing TS types

Most likely you will want to share some typescript types/interfaces between your libraries and cloud-functions. For that, create an nx node library by nx g @nx/node:library shared-types,

It creates a shared-types folder under libs directory and updates the root tsconfig.base.json. Now you can create an interface and use this interface in your cloud function app: test-app-functions.

Image description

Image description

Cloud functions - Serving & Deployment

When you created your cloud function directory: test-app-functions (mine is called market-monitor-cloud-functions) it contains a package.json with some scripts to run the app.

I personally had trouble running those script from the cloud-function app directory so instead of that I introduced 2 scripts into the root package.json file. Those are:

"mm:cloud-function:serve": "nx build test-app-functions && firebase emulators:start --only functions --config firebase.test-app-functions.json",
"mm:cloud-function:deploy": "nx build test-app-functions && firebase deploy --only functions --config firebase.test-app-functions.json"
Enter fullscreen mode Exit fullscreen mode

When serving your app by the local emulator what you also may want to do is to update the firebase.test-app.json file at the root directory, precisely the emulators part. I only wanted to emulate the functions, so I removed the rest of the options and ended up with the following configuration:

// firebase.test-app.json
"emulators": {
    "functions": {
      "port": 5001
    },
    "singleProjectMode": true
  }
Enter fullscreen mode Exit fullscreen mode

Initiaze Functions to Firebase

The first thing you have to do when it comes to deploying cloud functions is to enable your project to pay-as-you-go:

Image description

If you have ever worked with firebase functions outside of nx, most of the times you connect your functions to your firebase app, is by exporting the private key (as suggested at the beginning), importing your key into the folder and the initializing the app as follows:

import * as admin from 'firebase-admin';
import { DATABASE_URL } from './environments';

const serviceAccount = require('../firebase_key.json');

admin.initializeApp({
  credential: admin.credential.cert(serviceAccount),
  databaseURL: DATABASE_URL,
});
Enter fullscreen mode Exit fullscreen mode

The config however didn’t work for me. I was having some weird path resolving errors so I ended up just by copying the firebase_key.json content directly into the credential part (which is not the ideal solution), as follows:

const serviceAccount: admin.ServiceAccount = {
  projectId: 'whatever-id',
  privateKey: '-----BEGIN PRIVATE KEY-----',
  clientEmail: 'firebase-adminsdk-knos0@something.gserviceaccount.com',
};

admin.initializeApp({
  credential: admin.credential.cert(serviceAccount),
  databaseURL: DATABASE_URL,
});
Enter fullscreen mode Exit fullscreen mode

After that I run the deployment command: yarn mm:cloud-function:deploy, it will successfully deploy my cloud functions to Firebase.

Image description

Image description

Summary

Honestly, the longer I am a developer the more technologies I have to use, however, once everything is set up I greatly appreciate the productivity it gives me.

Firebase is a great BAAS solution and NX had proven its usefulness throughout the years. Choose your frontend framework based on your preferences, however, I believe this stack is great for a side project that is intended to fail in the near future. Have fun 👋.

If you liked this article, consider following me on:
dev.to
LinkedIn
Personal Website
Github

Top comments (3)

Collapse
 
phong6698 profile image
Chiramet Phong Penglerd

I have an issue when I try to build the functions.

File '.../libs/shared/src/index.ts' is not under 'rootDir' '...\apps\firebase'. 'rootDir' is expected to contain all source files.
Enter fullscreen mode Exit fullscreen mode

Do you know what the problem might be?

Collapse
 
krivanek06 profile image
Eduard Krivanek

Hey Chiramet.

This may be due to multiple reasons. Check if:
1.) In your library, inside tsconfig.lib.json there should be only one entry for the include part: "include": ["src/**/*.ts"]. Sometimes happens that a path to a library is added there.
2.) Did you export the function from shared in the index.ts ?
3.) Check if all the paths are correct in tsconfig.base.json (root directory)

Collapse
 
phong6698 profile image
Chiramet Phong Penglerd

I checked all your 3 points and it looks right. But it still didn't work.
What I did now is instead of using nx g @nx/node:library I used nx g @nx/js:lib. It has some different configurations and it works for me.

Thank you anyways. And nice post! It was exactly what I needed 😊