Skip to content

Emulator

The emulator allows you to make changes to local, temporary data. By default it is a blank slate every time you start up an emulator.

Setup

I had a little trouble with the setup, but eventually figured it out. You need to have Java installed to run the emulator. For my Mac m2 I needed to install the Arm 64 DMG Installer.

WARNING

If you run into the error Error: It looks like you haven't used Cloud Firestore in this project before follow the instructions at this Stack Overflow thread.

Connect to the Emulator

js
// switch this to true to use the production data.
let production = false;

const firebaseConfig = {
  apiKey: ...,
  authDomain: ...,
  projectId: ...,
  storageBucket: ...,
  messagingSenderId: ...,
  appId: ...,
};

const app = firebase.initializeApp(firebaseConfig);
const db = firebase.firestore();
const auth = firebase.auth();
console.log(firebase.auth);

if (!production) {
  db.useEmulator("localhost", 8080);
  auth.useEmulator("http://localhost:9099");
}

I learned that using the auth pre-built UI doesn't connect to the emulator. But I don't think I would use that in a real site anyway.

Start the Emulator with Data

You can start the emulator with the previous data you had by running a specific command. This is not from the cloud, but whatever you are locally testing.

bash
firebase emulators:start --import=test-data --export-on-exit

It doesn't look like the test-data directory needs to exist to import. It will be the name of the directory for the exported data.

Copy production data to emulator

This script is heavily based off of this article.

It's a pain to start from scratch with given data. This is a way to get a copy of live data to the emulator that you can freely manipulate and it won't affect production.

This script uses sandbox-ca45d as the project ID (found in the app settings or firebase projects:list), and uses test-data for the directory where the data goes.

Name this file refreshdb.sh, put it in the root of the project, and run bash refreshdb.sh.

bash
set -e

# This was taken from this article: 
# https://medium.com/firebase-developers/how-to-import-production-data-from-cloud-firestore-to-the-local-emulator-e82ae1c6ed8

# 1. Make sure Python 3 and gsutil are installed
  # python3 -V
  # gsutil version

# 2. Make sure that billing is enabled (and set a limit of $2)
  # Note that this is just for alerts. It doesn't shut down the project if it goes over.
  # Firebase Console -> Spark Plan change to Blaze

# 3. Initial Setup. You should only need to do this once
  # firebase login
  # firebase projects:list
  # firebase use sandbox-ca45d
  # gcloud projects list
  # gcloud config set project sandbox-ca45d 

# 4. Optional, manual way to copy data
  # # 4.a Remove old data
  # rm -rf ./test-data
  # gsutil -m rm -rf gs://sandbox-ca45d.appspot.com/test-data

  # # 4.b Add new data
  # gcloud firestore export gs://sandbox-ca45d.appspot.com/test-data
  # gsutil -m cp -r gs://sandbox-ca45d.appspot.com/test-data .

# 5. Use this instead of 4

#Remove previous bucket if exists
delete_previous_version_if_exists() {
  #We either delete local folder and bucket object or just a bucket
  rm -rf ./test-data &&
  gsutil -m rm -rf gs://sandbox-ca45d.appspot.com/test-data ||
  gsutil -m rm -rf gs://sandbox-ca45d.appspot.com/test-data
}

export_production_firebase_to_emulator() {
  #Export production firebase to emulator bucket
  gcloud firestore export gs://sandbox-ca45d.appspot.com/test-data
  
  #Copy to local folder
  gsutil -m cp -r gs://sandbox-ca45d.appspot.com/test-data .
}

#Run bash functions, either delete previous bucket and local folder if exists for update or just export clean way
delete_previous_version_if_exists && export_production_firebase_to_emulator ||
export_production_firebase_to_emulator

firebase emulators:start --import=test-data --export-on-exit

For any subsequent sessions you can just run firebase emulators:start --import=test-data --export-on-exit which will preserve your data from production with whatever modifications you made. If you need to start with a mirror copy of production, you will need to run bash refreshdb.sh again.

WARNING

Every time you refresh data all of the authentication set up will disapear. ALSO I still need to test this script with cloud storage and functions and such. I have only tested this with Firestore.