Firebase Cloud Functions with firebase-backend package by FilledStacks

carlomigueldy

Carlo Miguel Dy

Posted on March 28, 2021

Firebase Cloud Functions with firebase-backend package by FilledStacks

Introduction

In this article, we will learn about how to use firebase-backend package by FilledStacks. Why does this package exist and why should we use it? Let's think of a scenario where your app will have a lot of cloud functions, you can export these into their own separate files but it might be challenging or you might have to structure it in a certain way it is maintainable and easier for you. Firebase Backend package handles this for you but we have to follow certain conventions otherwise during build your defined function wouldn't be recognized and will not be deployed, this means Firebase Backend is opinionated in my opinion.

There is a video tutorial for this package which Dane Mackier explains from Fireship's YouTube channel, so in case you haven't seen the video yet here is the link for you to watch

https://www.youtube.com/watch?v=W_VV2Fx32_Y

Also be sure to subscribe to Fireship and FilledStacks channel, they both produce quality content for Firebase and Flutter!

Otherwise if you prefer learning it here, continue to read!

Installation

Suppose you already have a Firebase project created from the console and in your code base as well, but make sure you enable Firebase Blaze plan to enable Cloud Functions. Now let's get right to it:

While you are in your root directory, install the package via NPM

$ npm install firebase-backend
Enter fullscreen mode Exit fullscreen mode

Once that is done we can then proceed to setup index.ts or index.js file. But in this article I will choose TypeScript so we will be setting up firebase-backend package on index.ts

import { FunctionParser } from "firebase-backend";
import * as admin from "firebase-admin";

admin.initializeApp();

exports = new FunctionParser(__dirname, exports).exports;
Enter fullscreen mode Exit fullscreen mode

Here we import FunctionParser from firebase-backend and we also import firebase-admin suppose that we will use Firestore with Admin SDK. This is the only place we initialize admin by admin.initializeApp()

Then we set the exports with the returned value from the FunctionPaser exports

File Structure

When using this package, your file structure would be in a feature based structure and have two sub-directories to distinguish whether it is a REST endpoint or a cloud function that is event driven based on Firestore queries (onCreate, onDelete, onUpdate, onWrite)

src/
 - orders
   - reactive
     - onOrderCreated.function.ts
   - restful
     - confirmOrder.endpoint.ts
index.ts
Enter fullscreen mode Exit fullscreen mode

orders is a feature folder then it contains reactive sub directory and restful sub directory. Where reactive are the ones that are event driven and listens to any changes from Firestore queries and the restful sub directory is our REST endpoints and can be accessible with any specified HTTP methods (GET, POST, PUT, DELETE, etc)

As you may have noticed under reactive folder we name the file as onOrderCreated.function.ts where onOrderCreated is the cloud function name and function will tell the FunctionParser that this is a cloud function, in its code we will also call it onOrderCreated

onOrderCreated.function.ts

import * as functions from "firebase-functions";

exports.onOrderCreated = functions.firestore
  .document('orders/{orderId}')
  .onCreate((snapshot, context) => {
     // code
  })
Enter fullscreen mode Exit fullscreen mode

alternative way of doing it is,

import * as functions from "firebase-functions";

export const onOrderCreated  = functions.firestore
  .document('orders/{orderId}')
  .onCreate((snapshot, context) => {
     // code
  })
Enter fullscreen mode Exit fullscreen mode

confirmOrder.endpoint.ts

And now for creating the REST endpoint we import Endpoint from firebase-backend and the enum RequestType as well to tell what HTTP method should be used to access this endpoint

import { Request, Response } from "express";
import { RequestType, Endpoint } from "firebase-backend";

export default new Endpoint(
  "confirmOrder/:id",
  RequestType.PATCH,
  (request: Request, response: Response) => {
  const params = request.params

  response.status(200).json({ message: `Order confirmed for ID ${params.id}` })
})
Enter fullscreen mode Exit fullscreen mode

And that's how we define our cloud functions and a REST endpoint

Building and deployment

Before anything else, we must install rimraf and make a little bit of configuration on or package.json file

Now install rimraf as a dev dependency via

npm i -d rimraf
Enter fullscreen mode Exit fullscreen mode

And let us then modify our package.json under scripts

"scripts": {
    ...
    "clean": "rimraf lib/",
    "prebuild": "npm run clean",
  },
Enter fullscreen mode Exit fullscreen mode

Now just add "clean" and "prebuild", where "prebuild" will always get executed every time you execute a build

Once that is done you can start up your emulators and test it out or you can then deploy your cloud function to Firebase servers.

Conclusion

The firebase-backend package definitely helped us to structure a production level code for our Cloud Functions, this means our Cloud Functions is maintainable, readable, and very good for debugging because of how we name things and how firebase-backend encourages us to do that.

This is still a new package by FilledStacks but definitely it is a good one and one I would use for any of my apps that will get built for production.

FilledStacks always impresses me so if you like Flutter be sure to check out https://www.filledstacks.com/

That is all I have and thank you for taking the time to read this article, I appreciate it and I am happy if this was anything that helped you out. Cheers!

💖 💪 🙅 🚩
carlomigueldy
Carlo Miguel Dy

Posted on March 28, 2021

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related