My journey as I learn Firebase
Tags: firebase
Published: 2023-06-09 14:21:16

I've learned Firebase in the past but because I've not used it since then it was like learning it all over again, I write this post more as a reference than an actually tutorial.

One thing is for sure Firebase is a bit tough to learn. It is supposed to be easy to use, but the doc is so intimidating and there are so many different concepts revolving around the platform that I found it rather exhausting to approach.

I feel like the first thing most people would want to know is what is the most conventional way to *use* it, and my answer would be: `firebase` !

## firebase-tools

Do not try to configure something from the console if there is a way to configure it locally on your computer using the firebase command line tool:

```
sudo npm install -g firebase-tools
```
This simple execution will make `firebase` command line tool available on your system.

From there you probably want to initialize a project, make sure you created the project in the console (on the website yeah) first, then in your project directory on your machine run this command (I would suggest you read all the article before running this command as it is one setup and have a lot to digest):

```
firebase init
```

Proceed to read to have a small grasp of `firebase` core features:

## Authentication

There is not much to say, that helps to create a login environment for you app. Make sure to activate this feature in the console if you need it.

## Firestore

This feature is like live database but more modern (?). I personally prefer using this because it can easily scale and is maybe more intuitive for new comers. You would also need to activate that in your console.

## Functions

An easy way to understand what functions are, is to imagine Homer Simpson behind the central console patiently waiting for any signal.
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/zq5iicxq6f41d6wicyal.png)
Signals can be of all kind (e.g. "user connected", "new account created", "new data inserted inside the database (firestore)", etc...).
When a signal is received Homer pushes a button to call the appropriate action/*function*, now a function can be anything you define. For instance you may want to push initialization data inside firestore when a new user register on your website.
`firebase init` will ask you if you want to write functions using *JavaScript* or *TypeScript*. I would recommend using *JavaScript* here because using ES Modules you still get type checking, and it lifts the burden to have to build every time you modify a file.

As I said signals are various events Firebase listened to, and when a particular event occurs, it runs a function if you've defined it.
Firebase provides a JavaScript package called `firebase-functions` and it's really straightforward. It provides an interface for signals so it easily reads what it does. Let's look at a small code snippet:

```javascript
import functions from 'firebase-functions/v1';
import {beforeUserSignedIn} from 'firebase-functions/v2/identity';

export const onUserCreate = functions.auth.user().onCreate(
  (user, context) => { /* ... */ }
);

export const onBeforeSignin = beforeUserSignedIn((e) => {
  // ...
});
```

All functions are accessible from the `firebase-functions/v1` path, here we use the `functions.auth.user().onCreate` signal to run a function (`(user, context) => ...`) when a new user is created.  
You can access most of functions from *v1*, but a better way to access functions/signals is to use *v2*, in the example you can see that we easily import `beforeUserSignedIn` function/signal and use it in the code, it helps with readability.

A function needs to be exported for Firebase to register it, the names `onUserCreate` and `onBeforeSignin` in this example are custom names, it doesn't have to be these values and you can write any name you want as far as they do not conflict.

### Querying your firestore from functions file

There is a difference between registering a function using `firebase-functions` interface, and querying the firestore which can be achieve with the `firebase-admin` package.
While `firebase-functions` provides a way to create functions, the `firebase-admin` module can be used to do various things related to Firebase features, the latter helps you write various logic execution when a function is triggered. Here's an example of how to populate data in firestore when a new user is created:

```javascript
import functions from 'firebase-functions/v1';
import admin from 'firebase-admin';

admin.initializeApp();

export const onUserCreate = functions.auth.user().onCreate(
  async (user, context) => {
    const firestore = admin.firestore();
    const userRef = firestore.doc(`users/${user.uid}`);

    await userRef.set({
      premium: false,
      bookmarks: [],
      website: ''
    });
});
```

## Emulators

If you've installed some emulators during `firebase init`, you can run them using the following command:
```
firebase emulators:start
```
and access `http:localhost:4000` to meet with the UI.

From here you have to tell your app to use the various emulators endpoint rather than the remote ones
For instance for Authentication you would use :

```typescript
import {getAuth, connectAuthEmulator} from 'firebase/auth';

export const firebaseAuth = getAuth();
connectAuthEmulator(firebaseAuth, 'http://127.0.0.1:9099');
```