Firebase & Google Cloud: What’s different with Cloud Functions?
In my prior post about Firebase and & Google Cloud Platform (GCP), I talked about some of the ways that Firebase relates to GCP. The main points were:
- A Firebase project is also a GCP project.
- An existing GCP project can be configured to add Firebase services.
- Firebase adds SDKs, tools, and configurations to some Google Cloud products for use in mobile and web applications.
I promised to expand more on the third point for each of the products that Firebase augments. Today, it’s Cloud Functions!
If you’re not familiar with Cloud Functions (Firebase, GCP), it’s Google’s serverless compute product that lets you deploy code that responds to HTTP requests and events from other Google products in your project. Event sources include Cloud Storage, Cloud Firestore, Firebase Realtime Database, and many others. So, for example, when a file gets uploaded to your Storage bucket, your code can receive an event for that. And when a document changes in Cloud Firestore, you can respond to that as well.
I, for one, love working with Cloud Functions. In my early app-building days, I always found it to be a pain to try to manage a backend for my app, even if it didn’t have to scale. Today, if I want to make a web API or some other backend, I just write and deploy code to Cloud Functions, and it all Just Works and scales. Now, without the responsibility of managing a backend, I get to spend more time working on the app.
Since my world of development exists primarily in the mobile space, I also spend a bunch of time with Firebase. This means that I prefer a Firebase-centric view of my software development tools. So, when I work with Cloud Functions, I typically do so with the tools and APIs provided by Firebase. However, I find it’s helpful to keep in mind that Cloud Functions is actually a Google Cloud product, visible from Firebase.
Cloud Functions is a Google Cloud product, visible from Firebase
I have a project where I’ve already deployed some functions with the Firebase CLI (more on that later). Here’s what the Cloud Functions dashboard looks like in the Firebase console:
You can see all the deployed functions in this project, along with some tabs at the top for more diagnostics. Between all these tabs, you can do all your typical work with Cloud Functions. For the function where the mouse pointer is hovering, there’s an overflow menu with additional options. One of those options is called “Detailed usage stats”, and you can see an icon there that indicates that you’re going to leave the Firebase console if you click it. Clicking the link opens a tab and takes you to the Cloud console (easy to spot with its blue and white UI theme), with even more detailed diagnostics for just that one function. There are also tabs for viewing the source code and other files deployed with the function, as well as a way to test the function.
If you click the “Edit” button at the top, you can change some of the properties of the function:
It’s worth noting that this console page is the only place you can set retries on failure for a background function that was deployed with the Firebase CLI. This is an important configuration that helps make sure your functions are as reliable as possible, assuming you’ve coded it correctly. (The checkbox for retries isn’t visible here — you have to scroll down a bit further.) This console page is also the only place where you can change the memory and timeout configured for your function after it’s already been deployed.
Essentially what we have here is a situation where the Firebase console delegates to the Cloud console for some deeper information and tasks that aren’t normally required during development. From here you can also navigate to the Cloud Functions dashboard inside the Cloud console, which is similar to the equivalent Firebase screen:
If you want to navigate to this dashboard directly, you can always navigate to the Cloud console directly, select your project from the dropdown at the top, then choose the Cloud Functions product in the left menu.
The Firebase console typically seeks to give you a simplified view of Cloud products. As you perform more advanced tasks, you’ll likely end up spending more time in the Cloud console. I find that it’s common to switch between them frequently, depending on my task at hand. Your typical daily work with Cloud Functions won’t be in either console, however. The most common work is writing code and deploying it with a CLI.
Cloud Functions has a Cloud CLI and a Firebase CLI
As I mentioned before, my view of software development is mostly through the eyes of a mobile developer who uses Firebase for most backend functionality. As such, I tend to prefer the Firebase CLI to deploy to Cloud Functions. You should probably know that there is also a Cloud CLI called gcloud that you can also use to deploy functions. Both are effective at deploying functions.
The Firebase CLI offers some unique conveniences:
- A special API (with TypeScript type bindings!) for strongly-typed handling of events from supported event sources — see the firebase-functions npm module.
- Simultaneous deployment of multiple functions with a single, ultra-easy command line.
- Function configuration in code, next to the function code itself.
gcloud gives you these benefits:
- Support for handling any type of event source through a unified API.
- Function configuration on the command line during deployment.
- Deployment from your local file system, or remote sources (including mirroring from GitHub or BitBucket).
- Deployment of code written in Python (in beta) and Go 1.11 (in beta).
- Additional commands for working with deployed functions.
These two CLIs serve mostly different needs, and you can’t use one CLI to deploy all the same code as the other, simply because their deployment configurations are different. However, there’s nothing really preventing you from using both CLIs in tandem, as each provides its own advantages. For example, if you enjoy working with the customized APIs provided for each event source by firebase-functions and the Firebase CLI, you are almost certainly going to use the Firebase CLI for deployment (the APIs don’t work with gcloud). And did I mention those TypeScript type bindings? 😁 However, gcloud gets you closer to the Cloud Functions product itself and lets you perform more power-user actions. So give them both a try and see how they could work well for you.
Firebase offers a client SDK for invoking Cloud Functions
It’s very common for mobile apps to invoke backend APIs via an HTTP request. Firebase makes this easier for developers by providing a special kind of “callable” function, which is a wrapper around normal HTTP functions. For client apps, Firebase provides a library that makes it easy to directly invoke callable functions without having to manage the details of an HTTP client library. When you use the Firebase SDK to invoke a callable function, these tasks are performed automatically, reducing the amount of boilerplate code you have to write on both the client and backend:
- Sending and validating the user’s ID token (when logged in with Firebase Authentication).
- Sending the device instance id.
- Serializing and deserializing all request and response objects in JSON format.
Cloud Functions integrates with Firebase Hosting
Since Cloud Functions offers HTTP triggers, you can easily use them for webhooks and REST APIs. What your API consumers may not appreciate, however, is the URL that your function is given by default. Assuming that your Cloud project name is “your-project”, and you’ve deploy to region “us-central1”, a function called “helloWorld” will look like this:
It’s not exactly the most memorable URL. If you have a public API for other developers to consume, you might want to attach that to your domain instead. With Firebase Hosting, you can do that. Firebase Hosting is normally used to distribute static web content around the world, but you can also use it as a proxy for Cloud Functions. All you have to do is connect your domain with Firebase Hosting, then connect Firebase Hosting with Cloud Functions and rewrite a path forward to your Cloud Function endpoint. With this, you can have a more strongly branded endpoint:
On top of that, you can configure Firebase Hosting to enable edge caching of your function’s response so that it’s served faster, and you don’t pay the cost of a function invocation each time.
Firebase offers unique tools and SDKs for mobile developers who want to use Cloud Functions, building on top of the core product. So, if you do any mobile development, be sure to check out both the Firebase and Cloud perspectives of Cloud Functions.