I have recently been working on a React/Firebase side project to level up my skills and provide a playground to experiment with different techniques, patterns and libraries. One of my favorite features in Firebase is the Local Emulator Suite.
The Firebase Local Emulator Suite is a set of advanced tools for developers looking to build and test apps locally using Cloud Firestore, Realtime Database, Authentication, Cloud Functions, Pub/Sub, and Firebase Hosting. It provides a rich user interface to help you get running and prototyping quickly.
The Local Emulator Suite is fairly easy to set up but be sure to reference the docs for full details.
Regarding the actual code in your project, you first need to make sure the emulator ports are defined in your firebase.json
file like so ...
firebase.json
"emulators": {
"auth": {
"port": 9099
},
"firestore": {
"port": 8080
},
"ui": {
"enabled": true,
"port": 4000
}
}
Then in your app's firebase.js
file, include an if statement that checks your Node environment. If you are in 'development' mode your app will automatically run against the emulators and will use the ports that you defined in your firebase.json
file.
firebase.js
import firebase from 'firebase/app';
import 'firebase/auth';
import 'firebase/firestore';
export const firebaseConfig = {
apiKey: process.env.REACT_APP_FIREBASE_API_KEY,
authDomain: process.env.REACT_APP_FIREBASE_AUTH_DOMAIN,
databaseURL: process.env.REACT_APP_FIREBASE_DATABASE_URL,
projectId: process.env.REACT_APP_FIREBASE_PROJECT_ID,
storageBucket: process.env.REACT_APP_FIREBASE_STORAGE_BUCKET,
messagingSenderId: process.env.REACT_APP_FIREBASE_MESSAGING_SENDER_ID,
appId: process.env.REACT_APP_FIREBASE_APP_ID,
measurementId: process.env.REACT_APP_FIREBASE_MEASUREMENT_ID
};
if (!firebase.apps.length) {
firebase.initializeApp(firebaseConfig);
}
const app = firebase.app();
const auth = firebase.auth();
const db = firebase.firestore();
if (process.env.NODE_ENV === 'development') {
console.log('testing locally -- hitting local auth and firestore emulators');
auth.useEmulator('http://localhost:9099/');
db.useEmulator('localhost', 8080);
}
console.log(app.name ? 'Firebase Mode Activated!' : 'Firebase not working :(');
Now navigate to the root of your project in your terminal and start the emulators by running firebase emulators:start
. You should see this in your terminal
and the Emulator UI at http://localhost:4000
Now that you have emulators set up and running, it is time to seed the data to Firestore to develop against.
Seeding Data to Firestore Local Emulator
When developing locally it is helpful to have a data set to work with. While there are a few approaches to seeding data, including this approach via the Firebase docs, I chose to go with a simple script.
Create a script in your project root called dbseed.js
.
dbseed.js
const admin = require('firebase-admin'); // required
const faker = require('faker'); // amazing library!
// initialization
const projectId = 'your-firebase-project-id';
process.env.FIRESTORE_EMULATOR_HOST = 'localhost:8080';
admin.initializeApp({ projectId });
const db = admin.firestore();
// seed function
function getSeedData() {
try {
[...Array(10).keys()].map(() =>
db.collection('events').add({
author_name: faker.name.firstName() + '' + faker.name.lastName(),
author_profile_pic: faker.image.imageUrl(),
title: faker.commerce.productName(),
description: faker.commerce.productDescription(),
address: {
addr_1: faker.address.streetAddress(),
addr_2: faker.address.secondaryAddress(),
city: faker.address.city(),
state: faker.address.state(),
zipCode: faker.address.zipCode()
}
})
);
console.log('database seed was successful');
} catch (error) {
console.log(error, 'database seed failed');
}
}
getSeedData();
This script contains the required imports and initialization and runs a function that writes an array of objects to an 'events' collection.
Once the emulator suite is running, navigate to Firestore Emulator UI then run node dbseed.js
in a separate terminal window/tab.
You will see that the empty Firestore db is seeded with an array of Faker objects. Faker.js is an amazing library. Be sure to check out all the options at the https://github.com/marak/Faker.js/
Success! Now you can develop against test data while work within the Firebase Local Emulator Suite.
What about working with real production data?
You can also work with your production data if that is a better fit. Set up is more involved but still a nice approach. Check out the Firestore Docs to learn how to export your production data then import it when starting the emulators.
Conclusion
Working with mock data is an essential part of development and is something that I struggled with when working in the Firebase Local Emulator Suite. This simple approach allows me to seed the database quickly. Thanks for reading and I hope this helps your workflow. Happy coding!
Top comments (6)
Congrats on your first post!
@sethburtonhall wondering if you considered using the
@firebase/rules-unit-testing
library for seeding data.I haven't, will look into it though. Thanks!
Fantastic!
this gives me an 'app/invalid-credential' error. I've never understood how to do initializeApp with a local emulator, how can you provide a projectId if its a local emulator?
I was also wrestling with this. I haven't tested it, but I suspect this post uses real credentials and a real Firebase project, which is initialized with
firebase login
orfirebase use
.In my case, I wanted to seed a "demo-" project that can not connect to real services (the docs on
demo-
projects are vague and scattered). I was getting invalid (default) credential errors too when trying to connect to my emulators via a separate Node.js script.What worked for my
demo-test
project was:dbseed.js
#!/usr/bin/env node
shebang on top.process.stdin.resume();
line on the bottom to prevent the seed process from exiting (becauseemulators:exec
below would otherwise kill the emulators after the seeding is done, see below).It proved important to not try to call
db.settings({...})
with the host of my local Firestore Emulator etc, I suppose these should be automagically configured by the environment variables exported by the Firebase Emulator.Execution
This executes the seed script with credentials available from the context.