Web Development

Introduction To Firebase Cloud Functions


Web and mobile application often require back-end code to execute tasks like: sending out notifications or processing long running tasks (e.g. scaling images etc). In the traditional approach this back-end code is running on a server.

Recently Google’s Firebase introduces a new functionality which is called Cloud Functions. With this new service Firebase offers a scaleable solution for running back-end code in the cloud. Running code in the cloud has various advantages:

  • You do not need to run and maintain your own server
  • You do have an isolated code base for back-end code
  • You only get billed for the actual executing time of you code
  • The cloud infrastructure is highly scaleable

In the following tutorial you’ll get an overview of Firebase Cloud Functions. We’ll be building a sample application step-by-step so that you can follow along the way and deepen your knowledge of this Firebase feature.

Triggers

The functions you write can respond to events generated by Firebase and Google Cloud features. We will call these features triggers. Before starting to develop our first cloud functions let’s explore the most common triggers you can use for Cloud Functions in the following.

Realtime Database Triggers

With Realtime Database Triggers we’re able to respond to changes in the Firebase Realtime Database. To do so we need to register for events on a specific database path like:

functions.database.ref('/foo/bar')

The functions.database.ref function is called and the database path we would like to register for is passed in as a parameter.

It’s also possible to define a part of the path as a wildcard by surrounding this part with curly braces, like you can see in the following:

functions.database.ref('/profiles/{userID}')

If you’re just using the ref function, your registering for all events which are write, create, update and delete. If you just want to subscribe to one event you can use the following functions in addition:

  • onWrite(): is activated when the data is created, destroyed, or changed
  • onCreate(): is activated when new data is created
  • onUpdate(): is activated when data is updated
  • onDelete(): is activated when data is deleted

E.g. if we only want a cloud function to be executed if a new user profile unter /profiles/ is created we’re able to register an event handler with the following code:

exports.newUserCreated = functions.database.ref('/messages/{userID}').onCreate(event => { ... });

In this case the userID value can be accessed with event.params.userID inside the event handler function.

Authentication Triggers

By using authentication triggers you’re able to execute code in response to the creation and deletion of a user account via Firebase Authentication.

To create an event handler function which is executed if a new user is created you need to use the following code:

exports.newUserCreated = functions.auth.user().onCreate(event => { ... });

According to the Firebase documentation this trigger is invoked in the following cases:

  • A user creates an email account and password.
  • A user signs in for the first time using a federated identity provider.
  • The developer creates an account using the Firebase Admin SDK.
  • A user signs in to a new anonymous auth session for the first time.

A Cloud Functions event is not triggered when a user signs in for the first time using a custom token.

If you would like to access further information about the user profile you can use the event.data object within the event handler method. The event.data object is of type UserRecord, so that you can access properties like displayName (The user’s display name) or email (the user’s primary email).

In the opposite case you need to use the following code if you want to register an event handler for the user deletion event:

exports.userDeleted = functions.auth.user().onDelete(event => { ... });

CLOUD STORAGE TRIGGERS

With Cloud Storage Triggers you can trigger a the execution of a Firebase Cloud Function in response to uploading, updating, or deleting of files and folders in Google Cloud Storage. To register an event handler function we need to use the functions.storage object in the following way:

exports.storageChanges = functions.storage.object().onChange(event => {...});

Herewith we’re registering an event handler for all object changes on the default storage bucket. If you want to specifiy a specific storage bucket you need to add the call of the bucket function as well:

exports.storageChanges = functions.storage.bucket('bucketName').object().onChange(event => {...});

Within the event handler function you can make use of various storage attributes:

  • event.data: The storage object
  • event.data.bucket: The storage bucket which contains the file
  • event.data.name: The file path of the file in the bucket
  • event.data.contentType: The file content type
  • event.data.resourceState: Either ‘exists’ or ‘not_exists’. The ‘not_exists’ value is set if the file / folder has been deleted.
  • event.data.metageneration: Number of times the metadata of the file has been generated, for new objects the initial value is 1.

A typical use case for a Firebase Cloud Function which is registered for a storage trigger is a task is needed to fruther process a file, e.g. generate a thumbnail for an uploaded image file.

HTTP TRIGGERS

Another trigger type which can be used with Firebase Cloud Functions are HTTP Triggers. These triggers can be invoked through an HTTP request and can be registered by using functions.https in the following way:

exports.httpTest = functions.https.onRequest((req, res) => {...});

As you can see the event handler functions gets two parameters: req and res. The req objects (which is a Request object from the Express framework) gives you access to the properties of the original HTTP request sent by the client. The res object can be used to send a response to back to the client.

Analytics Triggers

By using Google Analytics for Firebase you’re able to understand in detail how the user interacts with your application iOS or Android app. Therefore the the Analytics API exposes various events. Events of type conversion events can be used to register Cloud Functions in the following way:

exports.onPurchase = functions.analytics.event('in_app_purchase').onLog(event => {...});

In this case we’re registering an event handler for the conversion event in_app_purchase.

Let’s try it out

Now, that you have a first overview of what Firebase Cloud Functions are and which type of triggers can be used to invoke those functions, let’s try out to implement some sample functions.

Installing Firebase CLI

Before initiating a cloud functions project we need to make use that the Firebase Command Line Client is installed and that the latest version is available on your system. The Firebase CLI is available as an NPM package. Execute the following command to install the firebase-tools package:

$ npm install -g firebase-tools

Initiate A New FirebAse Cloud Functions Project

Having installed the Firebase CLI in the last step, we’re now able to login to Firebase by using the following command:

$ firebase login

You’ll see the following response:

The browser should open up and load the URL which is displayed in the console automatically. If you have already an Firebase account you’ll be able to sign in. If you have not created a Firebase account yet, you need to do so first. Having logging in you’ll be able to see the following message:

At the same time the login is recognized by the Firebase CLI in the console:

Now you’re ready to create a new Firebase Cloud Functions project. First create a new empty project folder:

$ mkdir fb-functions

Then change into the newly created folder:

$ cd fb-functions

and execute the following command:

$ firebase init functions

You’re being asked to select the Firebase project you would like to use for the Firebase Cloud Functions project. You can also select the entry [create a new project] if you would like to add a new Firebase project to your account:

The next question you’re being asked is “Do you want to install dependencies with npm now?”. As we would like to add all necessary dependencies you need to say “Y” here or simply hit return as “Y” is the default setting.

Now you should be able to see something similar to

The Firebase CloudFunctions project has been setup successfully initiated.

Project Structure

Before starting with the implementation of the first Firebase Cloud Function let’s take a look at the project structure:

Here you can see that the structure of the project is quite simple:

  • firebase.json: Can contain settings for your Firebase project
  • functions/package.json: Contains a list of NPM package dependencies of this project
  • functions/index.js: Used for implementing Cloud Functions
  • functions/node_modules: Directory in which the NPM packages are installed which are listed in package.json

Implementing A First Cloud Function

Let’s first try out the HTTP trigger. Open file index.js and insert the following implementation:

const functions = require('firebase-functions');

exports.helloWorld = functions.https.onRequest((req, res) => {
    res.send("Hello from Firebase!");
});

This is the most basic form of a Firebase Cloud Function implementation based on an HTTP trigger. First we’re requiring a reference to the the firebase-functions library. The Cloud Function is implemented by calling the functions.https.onRequest method and handing over as the first parameter the function which should be registered for the HTTP trigger.

The function which is registered is very easy and consists of one line of code:

res.send("Hello from Firebase!");

Here the Response object is used to send a text string back to the browser, so that the user gets a response and is able to see that the Cloud Function is working.

To try out the function we now need to deploy our project to Firebase. Therefore we’re making use of the Firebase CLI again:

$ firebase deploy --only functions

The deployment is started and you should receive the following response:

If the deployment has been completed successfully and you get back the function URL which now can be used to trigger the execution of the Cloud Function. Just copy and paste the URL into the browser and you should see the following output:

If you’re opening up the current Firebase project in the back-end and click on the link Functions you should be able to see the deployed helloWorld function in the Dashboard:

You can also switch to the LOGS tab to get a detailed log output:

Another Example

Let’s implement another example which uses two Firebase Cloud Functions. The first function makes use of the HTTP trigger and takes a string via URL parameter and inserts that string into the Firebase Realtime Database. The second Cloud Function makes use of the Realtime Database Trigger and is listing to changes written to the database by the first function. Inside this function we’re reading out the inserted string value, convert it to uppercase and write it back to the database.

Let’s get started with the first function insertIntoDB. Insert the following code in the file index.js:

const functions = require('firebase-functions');

const admin = require('firebase-admin');
admin.initializeApp(functions.config().firebase);

exports.insertIntoDB = functions.https.onRequest((req, res) => {
    const text = req.query.text;
    admin.database().ref('/test').push({text: text}).then(snapshot => {
        res.redirect(303, snapshot.ref);
    })
});

First we need to require the firebase-admin module to be able to write to the Realtime Database. In addition we need to call the method initializeApp and pass in the Firebase configuration which is available via functions.config().firebase. The implementation of the insertIntoDB Cloud Function is done by using again a HTTP trigger by calling functions.https.onRequest. The function itself is passed in as a parameter. By using the Request object req we’re able to read out the URL parameter text first. Next we’re executing

admin.database().ref('/test').push({text: text})

to write the text string to the database path /test. E.g. if the URL is accessed and the URL parameter text is set to string “My text string” a new node ID is added as a subnode to /test and text property is inserted as a child element like you can see in the following:

The call of the push method is returning a promise, so that we can use the then method to execute code after the promise has been resolved (the database operation has been performed). In this case we’re using the Response object to call the redirect method to display the Firebase Realtime Database Console View in the browser.

Next, let’s implement the convertToUppercase Cloud Function which listens for changes to the database path /test/{pushId}/text:

exports.convertToUppercase = functions.database.ref('/test/{pushId}/text').onWrite(event => {
    const text = event.data.val();
    const uppercaseText = text.toUpperCase();
    return event.data.ref.parent.child('uppercaseText').set(uppercaseText);
});

In this case we’re extracting the properties value with event.data.val(). Next the toUpperCase method is executed to convert the string to uppercase and finally the uppercase value is written to the property uppercaseText in the same database node:

Further Use Cases

Firebase Cloud Functions are a powerful tool. The examples from this posts have given you a basic understanding of Cloud Functions. However, there are many more use cases for Cloud Functions. Take a look at the following list of possible use cases:

  • Send out user notifications in case of events
    • Send a welcome email when a user signs up
    • Send confirmation emails when users are subscribing / unsubscribing
  • Perform automated Realtime Database Tasks to keep the database up to date and clean
    • If a user account is deleted, delete user’s content from database as well
    • Track the number of elements in a Realtime Database list
  • Execute intensive tasks in the cloud instead of in you app
    • Automatically generate thumbnails for images which are uploaded into Cloud Storage
    • Send bulk emails to users
  • Integrating with third-party services
    • Translate text inserted into the Realtime Database by using Google Translate service
    • Process payments (e.g. with Stripe API)

 

The Complete Angular Course: Beginner to Advanced

Check out The Complete Angular Course: Beginner to Advanced with thousands of students already enrolled.

The most comprehensive Angular course. Build a real e-commerce app with Angular, Firebase and Bootstrap 4

The Complete Angular Course: Beginner to Advanced

  • This course covers Angular 4
  • Build real-world Angular applications on your own
  • Master the best practices
  • Troubleshoot common Angular errors

Go To Course


Using and writing about best practices and latest technologies in web design & development is my passion.

    View Comments
    There are currently no comments.

    *