-
Head over to firebase. Sign in and create a project.
-
Copy your project settings under Firebase SDK snippet into your local project (ie your project's
api key
,auth domain
,databaseURL
, etc) -
Create a file (firebase.js or config.js Any name that suits you is fine)
-
Inside the file, import firebase from 'firebase/app'
The above line imports one of firebase SDKS which is use to initialize our application. Firebase app(the core Firebase SDK) is always required and must be listed first. You can now have access to each of firebase product through the firebase namespace
Note The reason why we did not import everything from firebase ie import app from 'firebase' is that, loading the entire SDK is not efficient for production web apps
- Initialize firebase.
const app = firebase.initializeApp({
apiKey: process.env.REACT_APP_API_KEY,
authDomain: process.env.REACT_APP_AUTH_DOMAIN,
databaseURL: process.env.REACT_APP_DATABASE_URL,
projectId: process.env.REACT_APP_PROJECT_ID,
storageBucket: process.env.REACT_APP_STORAGE_BUCKET,
messagingSenderId: process.env.REACT_APP_MESSAGING_SENDER_ID,
appId: process.env.REACT_APP_ID
});
Optionally
- Install firebase CLI tools by running the command npm i -g firebase-tools
- Login into firebase using firebase login
This command connects your local machine with firebase and gives your access to your firebase projects
- Next, run firebase init
This command links your local app directory with firebase, generates a firebase.json file, and prompts you to specify a public root directory
- Finally, run firebase deploy
The recommended way to get the current user.
firebase.auth().onAuthStateChange(callback to return an observable)
My way is to use rxfire to return an observable:
import {authState} from 'rxfire/auth';
authState(auth());
await firebase.auth().createUserWithEmailAndPassword(email, password)
await firebase.auth().signInWithEmailAndPassword(email, password)
const provider = new firebase.auth.GoogleAuthProvider()
const provider = new firebase.auth.FacebookAuthProvider()
const provider = new firebase.auth.TwitterAuthProvider()
Github
const provider = new firebase.auth.GithubAuthProvider()
Popup
await firebase.auth().signInWithPopup(provider)
Redirect
await signInWithRedirect(provider);
await auth().signOut();
To use firebase cloud firestore, first you'll need to import firestore from firebase.
import firestore from 'firebase/firestore';
- Connect to a collection:
firestore.collection('books'); // returns a collection reference called books
- Connect to a document:
firestore.doc(`/books/id`); // returns a specific document refercence
All or 95% of cloud firestore is asynchronous and also promised based
- To resolve a promise you can either use the then and catch approach or the async and await approach.
- After successfully resolving the promise, a snapshot is returned. A snapshot is basically data at that particular point in time based on your query.
- QuerySnapshot is what is returned next.
A querySnapshot has the following properties:
- docs: An array that returns all of the documents in the snapshot
- empty: This is a boolean that lets us know if the snapshot was empty
- metadata: Metadata about this snapshot, concerning its source and if it has local modifications
- query: A reference to the query that you fired.
- size: The number of documents in the QuerySnapshot
A QuerySnapshot has some methods as well:
- docChanges(): An array of the changes since the last snapshot.
- forEach(): Iterates over the entire array of snapshots.
- isEqual(): Let's you know if it matches another snapshot.
QuerySnapshots typically hold onto a number of QueryDocumentSnapshots, which inherit from DocumentSnapshot and have the following properties:
-
id: The id of the given document.
-
exists: Is this even a thing in the database?
-
metadata: Pretty much the same as QuerySnapshot above.
-
ref: A reference to the the documents location in the database. …and the following methods:
-
data(): Gets all of the fields of the object.
-
get(): Allows you to access a particular property on the object.
-
isEqual(): Useful for comparisons. References allow you to access the database itself. This is useful for getting the collection that document is from, deleting the document, listening for changes, setting and updating properties.
- Create (add) a new document with auto-generated ID
firestore.collection('books').add(data); // returns a promise
// Alternatively
firestore.collection('books').set(data);
**Note: set also creates a new document if the documents being set does not exist **
- Get (read) all documents from a collection:
Here, I mostly use a library called rxfire to simplify things.
import { collectionData } from 'rxfire/firestore';
const bookCollectionRef = firestore.collection('books');
collectionData(booksCollectionRef, 'id'); // returns an observable
- Get a single document from a collection:
Here, I mostly use a library called rxfire to simplify things
import {docData} from 'rxfire/firestore';
const bookRef = firestore.doc(`/books/id`);
docData(bookRef, 'id'); // returns an observable
- Update a specific document in a collection:
firestore.doc(`/books/id`).update(data); // returns a promise
// Alternatively
firestore.collection('books').doc('id').update(data, {merge: true})
Note: updating a document without {merge: true} overwrites the entire document. But if {merge:true} is specified, prevents the entire document from being overwritten
**Also, there are two ways of updating/modifying a document in firebase. We have the update and set methods. Set is used to wipe out the entire properties of a document reference whiles the update method updates/modifies just a single propety and will not wipe out the entire object **
- Delete a specific document in a collection:
firestore.doc(`/books/id`).delete(); // returns a promise
To setup cloud functions locally, you'll need node pacakage manager(npm) and firebase CLI
- Install firebase tools globally on your local machine using npm:
npm i -g firebase-tools
- Intialize firebase functions:
firebase init functions
Here, a couple of question will be asked. Are you ready to proceed(choose: yes[y]), Select a project to link with, Language to use (javascript/typescript), Use Eslint(y/n), Install dependencies(choose: yes[y])
-
A folder called functions with it's dependecies will be created. All cloud function logic will be wriiten in a folder called index.js
-
Deploy cloud functions:
firebase deloy --only functions
not ready
not ready
Cloud firestore is a NoSQL document realated database similar to CouchDB and MongoDB. Instead of storing data in a traditional row and column table, in NoSQL, data are stored as collections of documents. Modeling a relational data in a NoSQL database can be a challenge especially coming from a SQL background since you have to unlearn most of the things under SQL.
Collections don't store data on their own. Collections are containers that holds multiple documents that can be queried.
Data in a kind of json format. The rule of thumb here is that it is important to make your collections large and your document small (1mb or smaller).
Because NoSQL is schemaless, it means that we have the flexibility to model relationships in a variety of ways.
- One to One
- One to Many
- Many to Many
- Root collection: Is a collection of documents in the root of your database.
- Embbed data on document: Here you can save object, arrays and other data types on the document. The important thing is that, it needs to be relatively small.(1mb or less) It is not ideal for documents that scales up to thousands of records.
- Nest sub-collection on a document: This allows one to scope a collection to a parent document hence creating a hierarchy structure.
Problem
- Let's say you have a list of user documents in a user collection.
- Under each user we have a collection that holds the levels of students in the University.
- Querying for all the number of users in level 100 will be difficult since the data is specifically scoped to that user. So you can't use it to query multiple users.
The solution
- Denormalize the data and save the collection as a root collection.
- After creating the root collection, you will need to save the user id of the associated user on each individual document.
- With this, we can reference multiple user Ids to create a many-to-many relationship.
- You'll first have to create a cloud firestore object.
firestore.collection('posts');
firestore.collection('posts').doc('1234dfadf34dfs');
firestore.collection('posts').doc('1234dfadf34dfs').collection('comments');
firestore.collection('posts').doc('1234dfadf34dfs').collection('comments').doc('33rerdf34545qd');
// or
firestore.doc('/path to the document')
Cloud firestore supports some SQLite-like queries
# Firebase CLI You can use firebase command line interface to create a complete firebase project just like you do using the graphical user interface in your firebase console dashboard.To use firebase cli, you must first of all install **firebase-tools** ```javascript npm i -g firebase-tools ```
After you're done installing firebase-tools, log into firebase by running the command javascript firebase login
- To create a firebase project, run the command:
firebase projects:create {project_name}
- Now the next step is to initialize firebase:
firebase init
- Select the services you'll want to use(cloud functions, firestore, database, storage)
- Next, choose an existing project or create a new one
- Now select your build folder. (choose build and select yes if asked whether your app is SPA)
- Done!
Note: In case you're adding multiple development environment, run the following commands:
- Select a second project to add by running the command:
firebase use --add
- Choose a project from the list
- Give the selected project an alias let's say production
- Switch to the development project by running the command:
firebase use default
First of all using the code below is a very bad idea because it is not a good idea to leak non-production environment details in a production application:
if (process.env.REACT_APP_DEPLOY_ENV='production') {
firebase.initializeApp(productionConfig)
} else {
firebase.initializeApp(developmentConfig)
}
Recommended Approach: Implicit initialization works by loading Firebase javascript from a special /__/ folder. When we deploy our app to Firebase this route will exist for us but locally we will need to do a little more work to set it up.
In your favorite code editor open up the build/index.html that was created by firebase init. At the top of the body tag you will see a series of Firebase related script tags, copy it.
Paste them in your public/index.html file at the top of the body tag. Feel free to remove features you are not using.
To authenticate your application with a provider like google, follow the steps below:
- Get the auth module from firebase
import firebase from 'firebase/app';
import 'firebase/auth';
const auth = firebase.auth();
- create a provider of your choice. Here we will use google provider
const provider = firebase.auth.googleAuthProvider();
- Sign in with google
const signInWithGoogle = () => auth.signInWithPopup(provider);
Moreover, using onAuthStaeChange, we can track the current user. This will fire or get called when a user is either loggedin or logged out. When that happens we either get a user object or null.
Claims are extra bit of information that is to be associated with an authenticated user. Settinng custom claims should not be done on the client side (in the browser). Custom claims should be set on the server instead using cloud functions.
Cloud functions allow us to run functions on the server and it is good for code you don't want to expose on the client and perform tasks that are not available to client users.
You can write cloud functions to trigger the following:
- Cloud Firestore
- Realtime Database
- Remote Config
- Firebase Authentication
- Google Analytics
- Crashlytics
- Cloud Storage
- Cloud Pub/Sub
- HTTP
(NB: Have node installed in the first place).
Step1: Install firebase-cli tools by running npm i -g firebase-tools
Step2: Login into firebase firebase login
Step3: Run firebase init
Step4: Select the tool you want Typescript or Javascript
Step5: Choose whether you want Eslint or not
Step6: Install all dependencies
This should be your setup:
const functions = require('firebase-functions');
const admin = require('firebase-admin');
// allows us to make calls to firestore on our local network
admin.initializeApp({
credentials: admin.credential.cert(require('fileToPath(admin.json)')),
databaseURL: "https://www.blahblah.com"
})
// you'll need to install express first
const express = require('express');
const app = express();
app.get('/helloWorld', (req, res) => {
res.send('Hello world');
})
exports.api = functions.https.onRequest(app);
Important Tip: How do you get your Service Account Credential? Steps:
- Go to your firebase project settings
- Under the Service accounts tab generate a new key
- This key comes in a json format, copy that file into your functions folder and require it
createdAt: new Date().toISOString()