Let's try Firebase

Photo of Łukasz Włodarczyk

Łukasz Włodarczyk

Dec 15, 2020 • 12 min read
woman working on a laptop

In a nutshell, Firebase is an ecosystem of Google tools that can be used to build full-stack applications.

It’s categorized as a backend-as-a-service (or BaaS) which gives developers the opportunity to create applications without the hassle of setting up the backend.

Key features
  • Authentication
  • Cloud Firestore
  • Realtime Database
  • Storage
  • Hosting
  • Cloud Functions
  • Machine learning

During my research, I created a chat app that utilizes a few of Firebase’s main features.

https://react-firebase-poc-1c7c7.web.app

First, you have to log in to the Firebase console, create a project, and add Firebase to your app.

https://console.firebase.google.com/

At that point, you should receive credentials that will let you connect Firebase with your app.

firebase.js

import firebase from 'firebase';

const config = {

apiKey: 'AIzaSyCNH_Y_8CyucgHOas4EPxSWX4to3tqj7fdA2sI',

authDomain: 'react-firebase-poc-1c7c7.firebaseapp.com',

databaseURL: 'https://react-firebase-poc-1c7c7.firebaseio.com',

projectId: 'react-firebase-poc-1c7c7',

storageBucket: 'react-firebase-poc-1c7c7.appspot.com',

messagingSenderId: '22747307388',

appId: '1:22747307388:web:7f1bgasd827487805fa48118f9',

measurementId: 'G-35J1425GSF02',

};


firebase.initializeApp(config);


export default firebase;

Authentication

Documentation: https://firebase.google.com/docs/auth/web/start

Once we have our app initialised, we can move on. Firebase offers plenty of sign-in methods. We will use three of them in our chat app.

sign-in methods

Before you start coding, you have to navigate to the authentication tab in the Firebase console and enable the methods you want to use.

authentication.js

import firebase from './firebase';


const auth = firebase.auth();


const googleProvider = new firebase.auth.GoogleAuthProvider();

const githubProvider = new firebase.auth.GithubAuthProvider();


export const signInWith = (provider) => async () =>

auth.signInWithPopup(provider).then((data) => {


const user = {

id: data.user.uid,

email: data.user.email,

isVerified: data.user.emailVerified,

};


return user;

});


export const signInWithGoogle = signInWith(googleProvider);

export const signInWithGithub = signInWith(githubProvider);


export const signOut = async () => auth.signOut();


export const signUpWithEmailAndPassowrd = async ({ email, password }) =>

auth.createUserWithEmailAndPassword(email, password).then((data) => ({

id: data.user.uid,

email: data.user.email,

isVerified: data.user.emailVerified,

}));


export const signInWithEmailAndPassowrd = async ({ email, password }) =>

auth.signInWithEmailAndPassword(email, password).then((data) => ({

id: data.user.uid,

email: data.user.email,

isVerified: data.user.emailVerified,

}));


export const verifyAuth = async (fn) => firebase.auth().onAuthStateChanged(user => {

if(user) {

// user logged in

} else {

/// user logged out

}

});

The authentication methods are very straightforward.

The signInWithPopup method takes the provider as an argument and returns some information from, for example, your Google account. In addition, you receive an access token, data.credential.accessToken, that will let you access more info from the Google API or other services.

onAuthStateChanged lets you check whether the user has an active session.

Storage

Documentation: https://firebase.google.com/docs/storage/web/start

Cloud Storage lets you upload and share user-generated content, such as images and video, which allows you to build rich media content into your apps.

In our chat app, we use it to store pictures uploaded by users.

storage.js

import firebase from './firebase';


const storage = firebase.storage();


export const uploadImage = async (image) => {

const name = image.name + Date.now();

const ref = storage.ref(`images/${name}`);


await ref.put(image);


const url = await ref.getDownloadURL();


return url;

};

storage.ref(`images/${name}`); creates the reference to the resource;
ref.put(image); uploads the image to the storage
await ref.getDownloadURL(); and finally, we can get a URL to the specific resource;

Firestore

Documentation: https://firebase.google.com/docs/firestore/quickstart

Cloud Firestore stores data in documents, which are stored in collections. Cloud Firestore creates collections and documents implicitly the first time you add data to the document. You do not need to explicitly create collections or documents.

If you’re not sure whether you should use Cloud Firestore or Realtime Database, check this survey → https://firebase.google.com/docs/database/rtdb-vs-firestore

Our app needs to store users and messages, so let's create a few functions that will let us create and retrieve this data.

firestore.js

import firebase from './firebase';

import * as storage from './storage';


const db = firebase.firestore();


export const createUser = async ({ id, email, isVerified }) =>

db.collection('users').doc(id).set({

id,

email,

isVerified,

});


export const createUserIfNotExist = async ({ id, email, isVerified }) =>

db

.collection('users')

.doc(id)

.get()

.then(async (doc) => {

if (doc.exists) {

return doc.data();

} else {

const user = await createUser({ id, email, isVerified });

return user;

}

});


export const createMessage = async ({ text, file, authorId }) => {

if (file) {

const url = await storage.uploadImage(file);


db.collection('messages').add({

value: url,

type: 'img',

authorId,

created: firebase.firestore.Timestamp.fromDate(new Date()),

});

}


if (text) {

db.collection('messages').add({

value: text,

type: 'text',

authorId,

created: firebase.firestore.Timestamp.fromDate(new Date()),

});

}

};

db.collection('users').doc(id).set({...}) creates a new document with a specified id in users collenction.

db.collection('messages').add({...}) also, you can let firebase to generate id for you.

firestore.js

...

export const listenForMessages = async (fn) =>

db

.collection('messages')

.onSnapshot(async (snapshot) => {

let newMessages = [];

snapshot.docChanges().forEach(function (change) {

if (change.type === 'added' || change.type === 'modified') {

newMessages.push({ id: change.doc.id, ...change.doc.data() });

}

});



...

});

Since we are building a chat, we need to set up a listener that will inform us about every change in the message collection. With Firestore, you can listen to a document with the onSnapshot() method. In our case, we listen only for new and updated messages.

More info:https://firebase.google.com/docs/firestore/query-data/listen

Cloud Functions

Documentation:https://firebase.google.com/docs/functions/get-started

Cloud Functions is a serverless framework that lets you automatically run backend code in response to events triggered by Firebase features and HTTPS requests. Your code is stored in Google's cloud and runs in a managed environment.

We will use this feature to moderate messages sent by users.

Let’s jump to a terminal for a minute. Execute:

firebase init

and select Functions.

image with code

After that command, you should have created a functions folder with index.js inside.

A cloud function lets us listen to changes in the Firestore message collection and run some code on every change. In our case, we want to check every new message, so we should use the onCreate method.

If the message contains a swear word, we moderate it and save the updated version.

functions/index.js

...

exports.moderator = functions.firestore

.document('messages/{messageId}')

.onCreate((snap) => {

const message = snap.data();



if (message && message.type === 'text') {

const moderatedMessage = moderateMessage(message.value);



console.log(

'Message has been moderated. Saving to DB: ',

moderatedMessage

);



return snap.ref.update({

value: moderatedMessage,

moderated: message.text !== moderatedMessage,

});

}

return null;

});

...

Hosting

With Firebase, we can host the app using a few commands in the terminal.

Make sure you have installed firebase-tools globally.

npm install -g firebase-tools

If you’re not logged in, do it with the command firebase login and select a project.

First, we have to build our app:

yarn build

Next, run:

firebase init

Choose your hosting:

image with code

firebase serve --only hosting

firebase deploy

And voilà, you should see a hosting URL in the terminal.

image with code

Repo→ https://github.com/LukeWlodarczyk/react-firebase-poc

Check out my app→ https://react-firebase-poc-1c7c7.web.app

Photo of Łukasz Włodarczyk

More posts by this author

Łukasz Włodarczyk

node.js Łukasz's programming fascinations are strongly associated with JavaScript technologies. He...
How to build products fast?  We've just answered the question in our Digital Acceleration Editorial  Sign up to get access

We're Netguru!

At Netguru we specialize in designing, building, shipping and scaling beautiful, usable products with blazing-fast efficiency
Let's talk business!

Trusted by:

  • Vector-5
  • Babbel logo
  • Merc logo
  • Ikea logo
  • Volkswagen logo
  • UBS_Home