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
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
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;
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
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
})
alternative way of doing it is,
import * as functions from "firebase-functions";
export const onOrderCreated = functions.firestore
.document('orders/{orderId}')
.onCreate((snapshot, context) => {
// code
})
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}` })
})
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
And let us then modify our package.json
under scripts
"scripts": {
...
"clean": "rimraf lib/",
"prebuild": "npm run clean",
},
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 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!