Firebase Functions in a nutshell
Firebase Functions in a nutshell
By Mohsen Mahabadi
7 min read
Firebase Functions is a powerful tool that allows developers to build and run backend code for their applications.
- Authors
- Name
- Mohsen Mahabadi
- linkedinMohsen Mahabadi
- Github
- githubmmahabadi
Before we begin, it should be noted that if you are not familiar with Firebase Functions, this article will get you right up to speed! If you are experienced with them, there might be some interesting pieces that you are unaware of.
Let's look at the Firebase Functions definition provided by Google:
Cloud Functions for Firebase is a serverless framework that lets you automatically run backend code in response to events triggered by Firebase features and HTTPS requests. Your JavaScript or TypeScript code is stored in Google's cloud and runs in a managed environment. There's no need to manage and scale your own servers.
Why do we need Firebase Functions
We no longer need to create, distribute, and maintain backend APIs thanks to Firebase Functions. For instance, when a new user signs up with Firebase Authentication and we want to store a record in our database, we also don't want to allow write access to our database from the front end, so we write and deploy a cloud function to handle that task instead. More use cases can be found here if you're interested.
Setup your project
Make sure Node.js
and firebase-tools
are set up on your computer before moving on because Firebase Functions run in a Node.js environment.
Initialize your project
Open the terminal and navigate to the folder where you want to create the project.
- Run
firebase login
- Run
firebase init firestore
- Run
firebase init functions
After these commands complete successfully, your project structure looks like this:
myproject
+- .firebaserc # Hidden file that helps you quickly switch between
| # projects with `firebase use`
|
+- firebase.json # Describes properties for your project
|
+- functions/ # Directory containing all your functions code
|
+- .eslintrc.json # Optional file containing rules for JavaScript linting.
|
+- package.json # npm package file describing your Cloud Functions code
|
+- index.js # main source file for your Cloud Functions code
|
+- node_modules/ # directory where your dependencies (declared in
# package.json) are installed
- After completing the setup, you can open the source directory in your favorite IDE and copy the following code on the
index.js
file.
// The Cloud Functions for Firebase SDK to create Cloud Functions and set up triggers
import * as functions from 'firebase-functions'
// the Firebase Admin SDK to access Firestore.
import * as admin from 'firebase-admin'
admin.initializeApp()
Trigger Firebase Functions
There are two methods for calling Firebase Functions. The functions can be called directly by the HTTP Triggers method or as part of an event called Background Triggers.
We can trigger some functions when a user signs up, or trigger a function by adding, updating, or deleting a record from the database. It can be run when the database event occurs.
HTTP Triggers
There are two ways to invoke a cloud function through the HTTP protocol: Endpoint requests and Callable functions.
Endpoint request
Endpoint requests allow you to trigger a function by making an HTTP request to a specific URL. This is useful for integrating with other services, or for triggering a function from a web or mobile app.
1. Request functions
Add the following code to the index file we previously created:
exports.helloWorld = functions.https.onRequest((request, response) => {
response.send(“Hello World!”);
});
To publish the function to Firebase, use the following command:
Firebase deploy --only functions
Then, in Firebase's functions section, you can see the function.
After you deploy an HTTP function, you can invoke it using its own unique URL. The URL can be found by going to the functions section.
The URL includes the following, in order:
- The region (or regions) to which you deployed your function. Some production functions may need to explicitly set the location to minimize network latency.
- Your Firebase project ID
- cloudfunctions.net
- The name of your function
For example, the URL to invoke helloWorld() looks like this:
https://us-central1-<project-id>.cloudfunctions.net/helloWorld
2. Redirecting
exports.toGoogle = functions.https.onRequest((req, res) => {
return res.redirect('https://www.google.com')
})
You will be redirected to google.com
whenever you access this URL, such as www.mydomain.com/toGoogle
.
Callable Functions
Callable functions provide a simple, secure way to invoke a function from a client app. They handle authentication and data serialization and allow you to return a response to the client directly, without the need for additional client-side code.
exports.greeting = functions.https.onCall((data, context) => {
const { name } = data
return `Hello, ${name}`
})
Assume that a button (called callBtn) exists and that we want to call our function by clicking on it. Our greeting function will be called each time you click the button.
const button = document.getElementById('callBtn')
button.addEventListener('click', (e) => {
const greeting = firebase.functions().httpsCallable('greeting')
greeting({ name: 'Rodney' }).then((res: { data: string }) => {
console.log(res.data)
})
})
Checking user authentication:
If in callable function we need to check whether the user is logged in or not, we can use following code:
exports.doSomething = functions.https.onCall((data, context) => {
if (!context.auth) {
//user hasn't logged in
throw new functions.https.HttpsError('unauthenticated', 'you must login.')
}
//do something
})
Background Triggers
Background triggers refer to events that trigger a Firebase Function without an explicit request from a client. These triggers can be triggered by events such as changes to a Firebase Realtime Database, or the creation of a new user, and so on.
Auth Events
These triggers allow you to respond to events related to user authentication, such as the creation of a new user account, the deletion of an existing user account, or a user signing in or signing out.
1. User onCreate:
This function will be triggered after adding a user. Note that you must return a value or promise for background triggers.
exports.sendWelcomeEmail = functions.auth.user().onCreate((user) => {
// ...
})
2. User onDelete:
This function is triggered when a user is deleted.
exports.deleteUser = functions.auth.user().onDelete((user) => {
console.log('user deleted', user.email)
return admin.firestore().collection('users').doc(user.uid).delete()
})
3. onAuthStateChanged:
When the user's state changes, this observer is triggered. For instance, the onAuthStateChanged observer is called when the user logs in.
//Auth listener
firebase.auth().onAuthStateChanged((user) => {
if (user) {
// user logged in
// do some tasks like closing modal and so
} else {
// user didn't log in
}
})
Storge Events
With regard to specific Cloud Firestore events, you can create callback functions for
- onCreate: triggered when a document is written for the first time.
- onUpdate: triggered when a document already exists and has any value changed.
- onDelete: triggered when a document with data is deleted.
- onWrite: triggered when onCreate, onUpdate, or onDelete is triggered.
For instance, we'd like to know when the user collection was last updated:
exports.updateLastUpdated = functions.firestore
.document(`documents/{id}`)
.onUpdate((snap, context) => {
const previousData = snap.before.data()
const newData = snap.after.data()
const docId = context.params.id
const shouldUpdateLastUpdated = previousData.lastUpdated === newData.lastUpdated
if (shouldUpdateLastUpdated) {
return admin.firestore().collection('documents').doc(docId).update({
lastUpdated: Date.now(),
})
}
return null
})
Firestore onSnapshot
This method allows you to listen to a document. A document snapshot will be created after calling the callback function. Then, another call updates the document snapshot each time the contents change. You can use this function, for example, to display an exchange list and the changes over time without refreshing the page.
firebase.firestore().collection("exchanges")
.onSnapshot(snapshot => {
const list = snapshot.map(item => {...item.data, id: item.id});
console.log(list);
});
Database Events
When events occur in your Firebase Realtime Database, you can use Firebase Functions to trigger other functions. As an example, you can use a function to automatically send a push notification to all users whenever a new message is added to a specific chat room in your database. These events include when data is written, updated, or deleted:
- onWrite: which triggers when data is created, updated, or deleted in Realtime Database.
- onCreate: which triggers when new data is created in Realtime Database.
- onUpdate: which triggers when data is updated in Realtime Database.
- onDelete: which triggers when data is deleted from Realtime Database.
import * as functions from 'firebase-functions'
import * as admin from 'firebase-admin'
admin.initializeApp()
exports.sendPushNotification = functions.database
.ref('/chat_rooms/{chatRoomId}/messages/{messageId}')
.onCreate((snapshot, context) => {
const message = snapshot.val()
const chatRoomId = context.params.chatRoomId
const messageId = context.params.messageId
const payload = {
notification: {
title: `New message in chat room ${chatRoomId}`,
body: message.text,
badge: '1',
sound: 'default',
},
}
return admin.messaging().sendToTopic(chatRoomId, payload)
})
This function listens to the path /chat_rooms/{chatRoomId}/messages/{messageId}
and when it detects a new message, it gets the message value from the snapshot snapshot.val()
, and the chatRoomId and messageId from the context. Then it creates a notification payload with the message title, body and badge, sound and sends the payload to the topic chatRoomId using the admin.messaging().sendToTopic()
method.
Please be aware that you need to set up the Firebase Cloud Messaging service to be able to send push notifications.
Analytics Events
For mobile and web apps, Firebase Analytics is a free, unlimited analytics tool that offers information on user engagement and app usage. Firebase Functions can be triggered in response to events in Firebase Analytics, allowing you to automate tasks based on user behavior. For instance, you can use a function to send a push notification to users who haven't opened your app in a certain amount of time.
Here's an example of a Firebase Function that triggers when a user logs an event in Firebase Analytics, and logs the event name and parameters to the console:
/**
* After a user has completed a purchase, send them a coupon via FCM valid on their next purchase.
*/
exports.sendCouponOnPurchase = functions.analytics.event('in_app_purchase').onLog((event) => {
const user = event.user
const uid = user.userId // The user ID set via the setUserId API.
const purchaseValue = event.valueInUSD // Amount of the purchase in USD.
const userLanguage = user.deviceInfo.userDefaultLanguage // The user language in language-country format.
// For purchases above 500 USD, we send a coupon of higher value.
if (purchaseValue > 500) {
return sendHighValueCouponViaFCM(uid, userLanguage)
}
return sendCouponViaFCM(uid, userLanguage)
})
You might want to access user attributes like the user's language and the event's value (valueInUSD) for a purchase-triggered function, as shown in this sample. This second attribute allows the sample function to test whether this is a high-value conversion event, in order to send a higher-value coupon to valuable customers.
Conclusion
In conclusion, Firebase Functions is a powerful and flexible tool that allows developers to build and run backend code for their applications. With its integration with other Firebase services, such as Realtime Database and Firebase Analytics, it provides a seamless way to automate tasks and respond to events in real-time. Whether it's sending push notifications, logging new data, or tracking user behavior, Firebase Functions provide a simple and efficient way to add custom logic to your application.
With its serverless architecture, it eliminates the need for managing infrastructure and allows developers to focus on building great apps. Whether you're a seasoned developer or just starting out, Firebase Functions is a valuable tool to add to your toolkit.
Resources
- Firebase Functions Tutorial by The Net Ninja
- Cloud functions documentation by Firebase
Upcoming events
The Test Automation Meetup
PLEASE RSVP SO THAT WE KNOW HOW MUCH FOOD WE WILL NEED Test automation is a cornerstone of effective software development. It's about creating robust, predictable test suites that enhance quality and reliability. By diving into automation, you're architecting systems that ensure consistency and catch issues early. This expertise not only improves the development process but also broadens your skillset, making you a more versatile team member. Whether you're a developer looking to enhance your testing skills or a QA professional aiming to dive deeper into automation, RSVP for an evening of learning, delicious food, and the fusion of coding and quality assurance! 🚀🚀 18:00 – 🚪 Doors open to the public 18:15 – 🍕 Let’s eat 19:00 – 📢 First round of Talks 19:45 – 🍹 Small break 20:00 – 📢 Second round of Talks 20:45 – 🍻 Drinks 21:00 – 🙋♀️ See you next time? First Round of Talks: The Power of Cross-browser Component Testing - Clarke Verdel, SR. Front-end Developer at iO How can you use Component Testing to ensure consistency cross-browser? Second Round of Talks: Omg who wrote this **** code!? - Erwin Heitzman, SR. Test Automation Engineer at Rabobank How can tests help you and your team? Beyond the Unit Test - Christian Würthner, SR. Android Developer at iO How can you do advanced automated testing for, for instance, biometrics? RSVP now to secure your spot, and let's explore the fascinating world of test automation together!
| Coven of Wisdom - Amsterdam
Go to page for The Test Automation MeetupCoven of Wisdom - Herentals - Winter `24 edition
Worstelen jij en je team met automated testing en performance? Kom naar onze meetup waar ervaren sprekers hun inzichten en ervaringen delen over het bouwen van robuuste en efficiënte applicaties. Schrijf je in voor een avond vol kennis, heerlijk eten en een mix van creativiteit en technologie! 🚀 18:00 – 🚪 Deuren open 18:15 – 🍕 Food & drinks 19:00 – 📢 Talk 1 20:00 – 🍹 Kleine pauze 20:15 – 📢 Talk 2 21:00 – 🙋♀️ Drinks 22:00 – 🍻 Tot de volgende keer? Tijdens deze meetup gaan we dieper in op automated testing en performance. Onze sprekers delen heel wat praktische inzichten en ervaringen. Ze vertellen je hoe je effectieve geautomatiseerde tests kunt schrijven en onderhouden, en hoe je de prestaties van je applicatie kunt optimaliseren. Houd onze updates in de gaten voor meer informatie over de sprekers en hun specifieke onderwerpen. Over iO Wij zijn iO: een groeiend team van experts die end-to-end-diensten aanbieden voor communicatie en digitale transformatie. We denken groot en werken lokaal. Aan strategie, creatie, content, marketing en technologie. In nauwe samenwerking met onze klanten om hun merken te versterken, hun digitale systemen te verbeteren en hun toekomstbestendige groei veilig te stellen. We helpen klanten niet alleen hun zakelijke doelen te bereiken. Samen verkennen en benutten we de eindeloze mogelijkheden die markten in constante verandering bieden. De springplank voor die visie is talent. Onze campus is onze broedplaats voor innovatie, die een omgeving creëert die talent de ruimte en stimulans geeft die het nodig heeft om te ontkiemen, te ontwikkelen en te floreren. Want werken aan de infinite opportunities van morgen, dat doen we vandaag.
| Coven of Wisdom Herentals
Go to page for Coven of Wisdom - Herentals - Winter `24 editionMastering Event-Driven Design
PLEASE RSVP SO THAT WE KNOW HOW MUCH FOOD WE WILL NEED Are you and your team struggling with event-driven microservices? Join us for a meetup with Mehmet Akif Tütüncü, a senior software engineer, who has given multiple great talks so far and Allard Buijze founder of CTO and founder of AxonIQ, who built the fundaments of the Axon Framework. RSVP for an evening of learning, delicious food, and the fusion of creativity and tech! 🚀 18:00 – 🚪 Doors open to the public 18:15 – 🍕 Let’s eat 19:00 – 📢 Getting Your Axe On Event Sourcing with Axon Framework 20:00 – 🍹 Small break 20:15 – 📢 Event-Driven Microservices - Beyond the Fairy Tale 21:00 – 🙋♀️ drinks 22:00 – 🍻 See you next time? Details: Getting Your Axe On - Event Sourcing with Axon Framework In this presentation, we will explore the basics of event-driven architecture using Axon Framework. We'll start by explaining key concepts such as Event Sourcing and Command Query Responsibility Segregation (CQRS), and how they can improve the scalability and maintainability of modern applications. You will learn what Axon Framework is, how it simplifies implementing these patterns, and see hands-on examples of setting up a project with Axon Framework and Spring Boot. Whether you are new to these concepts or looking to understand them more, this session will provide practical insights and tools to help you build resilient and efficient applications. Event-Driven Microservices - Beyond the Fairy Tale Our applications need to be faster, better, bigger, smarter, and more enjoyable to meet our demanding end-users needs. In recent years, the way we build, run, and operate our software has changed significantly. We use scalable platforms to deploy and manage our applications. Instead of big monolithic deployment applications, we now deploy small, functionally consistent components as microservices. Problem. Solved. Right? Unfortunately, for most of us, microservices, and especially their event-driven variants, do not deliver on the beautiful, fairy-tale-like promises that surround them.In this session, Allard will share a different take on microservices. We will see that not much has changed in how we build software, which is why so many “microservices projects” fail nowadays. What lessons can we learn from concepts like DDD, CQRS, and Event Sourcing to help manage the complexity of our systems? He will also show how message-driven communication allows us to focus on finding the boundaries of functionally cohesive components, which we can evolve into microservices should the need arise.
| Coven of Wisdom - Utrecht
Go to page for Mastering Event-Driven Design