How to create your first Firebase Cloud function
Tags: firebase, cloudfunctions, serverless
Published: 2020-05-30 15:51:36

---
title: How to create your first Firebase Cloud function
published: true
description: Create your first Firebase Cloud function
tags: firebase, cloud functions, serverless
---

_Originally posted in https://omarhoumz.com/blog/firebase-cloud-functions/_

In this post we will cover one small, but very much hyped, part of serverless; **cloud functions**. One of the solutions available is firebase's <a href='https://firebase.google.com/docs/functions' target='_blank' rel='nofollow noopener noreferrer'>"Firebase Cloud Functions"</a>.

We are going to:

1. Create and set up a Firebase project
2. Setup a Firebase cloud function
3. Deploy our first function
4. Setup a local dev environment

#### Requirements

I assume that you have node and npm installed on your machine.

#### Starter project

Before we start, let us set up a basic project to work with. I created some files and boilerplate code in <a href='https://github.com/omarhoumz/wr-firebase-clound-function/tree/master/001-create-a-firebase-function-start' target='_blank' rel='nofollow noopener noreferrer'>this repo</a> in the `001-create-a-firebase-function-start` folder.

Check the <a href='https://github.com/omarhoumz/wr-firebase-clound-function/blob/master/001-create-a-firebase-function-start/README.md' target='_blank' rel='nofollow noopener noreferrer'>readme file</a> on how to get started with the code.

### 1. Create and set up a Firebase project

#### Create a Firebase project

To create a firebase project:

- Go to the <a href='https://console.firebase.google.com/' target='_blank' rel='nofollow noopener noreferrer'>Firebase Console</a>
- Log in or create your account
- Once on the home page, click the big "Add project" button
- Enter a name for your project
- Click "Continue" and follow the steps

And voila, we have a Firebase project.

#### Setup our firebase project locally

First, we have to install the Firebase CLI tools:

```bash
npm install -g firebase-cli
```

Then, we login to Firebase from the terminal:

```bash
firebase login
```

This will open a browser tab for us to authenticate to Firebase console. Once authenticated successfully, we should have our terminal prompt back.

Next is to initialize a Firebase project locally:

```bash
firebase init functions
```

The command will guide us through the setup. It will ask about 3 things: the Firebase project (which we already created), Cloud Functions language (I chose JavaScript, you can also choose TypeScript), and whether or not to use ESLint (which I replied with a "yes, please" to).

If all goes well, we should see these files created.

```diff
-
+ .firebaserc
+ .gitignore
+ firebase.json
+ functions/.eslintrc.json
+ functions/.gitignore
+ functions/index.js
+ functions/package-lock.json
+ functions/package.json
```

In addition to some other files you see, these are the important ones:

- `.firebaserc`: stores your project aliases.
- `firebase.json`: lists your project configuration.
- `functions/package.json` node dependencies for our Firebase cloud function.

The file that we should take a look at now is `functions/index.js`. This is where we write our code for the cloud function.

Let us use this "helloWorld" example. Notice that I disabled the <a href='https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS' target='_blank' rel='nofollow noopener noreferrer'>`CORS` header</a> since we are in development.

```js
const functions = require('firebase-functions')

exports.helloWorld = functions.https.onRequest((request, response) => {
  // disable CORS header
  response.setHeader('Access-Control-Allow-Origin', '*')

  response.status(200).json({ message: 'And, hello from serverless!' })
})
```

### 3. Deploy our first cloud function

#### Test the Firebase function locally

Before we deploy, we want to test the function locally. To do so, let us `cd` into the `Functions` directory:

```bash
cd functions
```

And start a local emulator (this is provided by the firebase-cli tools):

```bash
npm run serve
```

After this runs, the function will be watched for changes, and the local URL should be logged in the console. Look for something like this:

```bash
✔  functions[helloWorld]: http function initialized (http://localhost:5001/YOUR_PROJECT_ID/us-central1/helloWorld).
```

In the link above, `YOUR_PROJECT_ID` and `us-central1` are the project id and the data center region for your Firebase project respectively. And `helloWorld` is the function name.

If we visit the URL and all goes well, we see this message:

```json
{ "message": "And, hello from serverless land!" }
```

#### Deploy the Firebase cloud function

Now, let us deploy our function. While still being in the functions directory, execute this command:

```bash
npm run deploy
```

The result of the command should have a public URL to trigger our function. It looks something like this:

```
https://${DATA_CENTER_REGION}-${YOUR_PROJECT_ID}.cloudfunctions.net/${FUNCTION_NAME}
```

#### Trigger the cloud function

Next, let us use the function in our project. To do that, we add a `div` in the `index.html` file to show a message:

```diff
/* index.html */
  <h1>Hello Firebase Functions</h1>
+ <h2 id="function-response"></h2>
+
```

And in the `index.js` file:

```js
// get the heading element
const messageDiv = document.querySelector('#function-response')

// a function that updates the heading
function updateMessage(message) {
  messageDiv.innerText = message
}

// make sure to replace these info with yours
const YOUR_PROJECT_ID = 'YOUR_PROJECT_ID'
const DATA_CENTER_REGION = 'DATA_CENTER_REGION'
const FUNCTION_NAME = 'FUNCTION_NAME'

// the function trigger endpoint
const url = `https://${DATA_CENTER_REGION}-${YOUR_PROJECT_ID}.cloudfunctions.net/${FUNCTION_NAME}`

// trigger the function and get the result back
fetch(url)
  .then((result) => result.json())
  // when we have the result, we update the heading with the message
  .then((data) => updateMessage(data.message))
```

After we made these changes, let us check the result. Run the dev server:

```bash
npm run start
```

If everything went well, we should see in our browser a message like this:

```text
Hello Firebase Functions
And, hello from serverless land!
```

### 4. A better local development setup

When we are in development, we don't want to constantly deploy our function to see the result. So, we will leverage the local emulator provided by the Firebase CLI tools to have a better local development setup.

We know how to start the function emulator:

```bash
cd functions && npm run serve
```

We know how to start our dev server:

```bash
parcel ./index.html
```

Now, we need a way to start both of them with one command. Here is the easiest way I could find:

```bash
(cd functions && npm run serve) & parcel ./index.html
```

And to keep this setup, we're gonna edit the scripts in our `package.json` file:

```diff
"scripts": {
-  "start": "parcel ./index.html"
+  "start:frontend": "parcel ./index.html",
+  "start": "(cd functions && npm run serve) & npm run start:frontend"
},
```

And now we can use one command to start them both:

```bash
npm run start
```

For the `url` variable, we should modify it to accomodate for the environment (development vs production):

```js
const url =
  process.env.NODE_ENV === 'production'
    ? `https://${DATA_CENTER_REGION}-${YOUR_PROJECT_ID}.cloudfunctions.net/${FUNCTION_NAME}`
    : `http://localhost:5001/${YOUR_PROJECT_ID}/${DATA_CENTER_REGION}/${FUNCTION_NAME}`
```

And now that we use the local url of the function, we can remove the `CORS` header in the function:

```diff
- // disable CORS header
- response.setHeader('Access-Control-Allow-Origin', '*')
+ // disable CORS header for development
+ if (process.env.NODE_ENV !== 'production') {
+   response.setHeader('Access-Control-Allow-Origin', '*')
+ }
```

And then deploy the function:

```bash
cd functions && npm run deploy
```

### Summary

Until this point, we created a Firebase project using the Firebase console. In our local machine, we initialized our project a Firebase function and deployed it. We also configured a better setup for local development.

There is still much we can do here. We will explore other things in the next posts. But, if you are in a hurry, you can check the <a href='https://firebase.google.com/docs/functions' target='_blank' rel='nofollow noopener noreferrer'>the Firebase Functions docs</a>.