'How to setup and use Firebase cloud function emulator: No Firebase App '[DEFAULT]' has been created

This page instructs me to get a firebase project started, get an app started, and install firebase tools. I've done it, and with the code on the page that begins...

const functions = require('firebase-functions');

The trigger function suggested on that page, that starts like this...

exports.makeUppercase = functions.firestore.document('/messages/{documentId}')
      .onCreate((snap, context) => {

...works great. On that very same page, it shows me how to "Connect your app to emulators", with the recommended code like this...

import { getFirestore, connectFirestoreEmulator } from "firebase/firestore";

// firebaseApps previously initialized using initializeApp()
const db = getFirestore();
connectFirestoreEmulator(db, 'localhost', 8080);

But this code uses the module style and, the emulator code I started in the background errors out saying:

import "firebase/functions"; ^^^^^^

SyntaxError: Cannot use import statement outside a module

Why did the doc (on the very same page) instruct me to use two incompatible syntax styles? I figure the more modern (module) style is better, and a little googling led me to understand that I can upgrade my functions/index.js to a module by saying this in package.json:

  // stuff before this
  "engines": {
    "node": "16"
  },
  "main": "index.js",
  "type": "module",
  "dependencies": {
  // stuff after this

After that, the original require doesn't work, but more googling, and I think I can change it to this....

//const functions = require("firebase-functions");
import  "firebase/functions";

Is that right so far? I hope so, but now the console error from the emulator says this:

FirebaseError: Firebase: No Firebase App '[DEFAULT]' has been created

  • call Firebase App.initializeApp() (app/no-app). at getApp (file:///yada/yada/functions/node_modules/@firebase/app/dist/esm/index.esm2017.js:469:29)

I just want to try out some cloud functions. How do I get it working? Here's my whole, not-working functions/index.js...

//const functions = require("firebase-functions");
import  "firebase/functions";

import { getFirestore, connectFirestoreEmulator } from "firebase/firestore";
import { doc, collection, setDoc, deleteDoc } from "firebase/firestore"; 

// firebaseApps previously initialized using initializeApp()
const db = getFirestore();
connectFirestoreEmulator(db, 'localhost', 8080);


exports.makeUppercase = functions.firestore.document('/messages/{documentId}')
    .onCreate((snap, context) => {
      const original = snap.data().original;
      console.log('Uppercasing', context.params.documentId, original);
      const uppercase = original.toUpperCase();
      return snap.ref.set({uppercase}, {merge: true});
    });

exports.onMyCollectionWrite = functions.firestore.document('/collectionA/{docId}/subcollection/{subDocId}')
    .onWrite((change, context) => {

    // here, I want to use things like:
    // const promise = setDoc(collection(db, 'someCollection','someId), { someKey: 'some value' });
    // return promise.then(() => console.log('done'));

    });

I also hope to learn how I'll need to change this file once it's ready to be deployed to work on the real database.



Solution 1:[1]

You'll receive that error as you're missing Firebase App Initialization. You should initialize using this code:

const firebaseConfig = {
    apiKey: "xxxxx",
    authDomain: "xxxxx.firebaseapp.com",
    databaseURL: "https://xxxxxx",
    projectId: "xxxxxxx",
    storageBucket: "xxxxxx.appspot.com",
    messagingSenderId: "xxxxxxx",
    appId: "xxxxxxx",
    measurementId: "xxxxxx"
};

const app = initializeApp(firebaseConfig);

You can get the config by navigating to your Firebase Project Settings > Your Apps > SDK setup and configuration. You could also check this documentation for more information. ***

You're just importing your configuration here if ever you want to work with your real database.


Note: When connecting to the Cloud Firestore emulator from any other environment, you will need to specify a project ID. You can pass a project ID to initializeApp directly or set the GCLOUD_PROJECT environment variable. Note that you do not need to use your real Firebase project ID; the Cloud Firestore emulator will accept any project ID, as long as it has a valid format. You can find more information here.


Also, I just want to point out that you're still mixing two different syntax which is the v9 (modular) and v8 (namespaced). You'll still receive an error after fixing the No Firebase App '[DEFAULT]' has been created. The error should be like this:

ReferenceError: exports is not defined in ES module scope

If you plan to use the modular version then you also should change how you export your functions. See sample code below:

export const makeUppercase = functions.firestore.document('/users/{documentId}')
.onCreate((snap, context) => {
    const original = snap.data().original;
    console.log('Uppercasing', context.params.documentId, original);
    const uppercase = original.toUpperCase();
    return snap.ref.set({uppercase}, {merge: true});
});

Here's a full sample code of which you could use all the Firebase emulator:

import { getFunctions, connectFunctionsEmulator } from "firebase/functions";
import { initializeApp, getApp } from "firebase/app";
import { getFirestore, connectFirestoreEmulator } from "firebase/firestore";
import { getAuth, connectAuthEmulator } from "firebase/auth";
import { getStorage, connectStorageEmulator } from "firebase/storage";
import { getFunctions, connectFunctionsEmulator } from "firebase/functions";

const firebaseConfig = {
// your-config
};

initializeApp(firebaseConfig);

const db = getFirestore();
const auth = getAuth();
const storage = getStorage();
const functions = getFunctions(getApp());

// Do this to check whether you're on an emulator or not. (Only if you're on the frontend side)
if (window.location.hostname === "localhost") {
  connectFirestoreEmulator(db, "localhost", 8080);
  connectAuthEmulator(auth, "http://localhost:9099");
  connectStorageEmulator(storage, "localhost", 9199);
  connectFunctionsEmulator(functions, "localhost", 5001);
}

export const functionName = async () => {
  // do something
};  

Here's some documentation that you can start with:


Note: If you plan to use the modular version then make sure to check Web Version 9 from the documentation as you would encounter issues when you use Web Version 8.

If you're still unsure what to use, then I would suggest using the compat versions as you can use namespace and modular version with the same import. You check it out here.


Update:

The above codes are for guide purposes only which shows how you can connect to the emulator, I also added some notes regarding the firebaseConfig above. For your use-case, you should only be using Firestore and Functions emulator. See sample code below:

const functions = getFunctions(getApp());
const db = getFirestore();
connectFunctionsEmulator(functions, "localhost", 5001);
connectFirestoreEmulator(db, 'localhost', 8080);

export const makeUppercase = functions.firestore.document('/users/{documentId}')
.onCreate((snap, context) => {
    const original = snap.data().original;
    console.log('Uppercasing', context.params.documentId, original);
    const uppercase = original.toUpperCase();
    return snap.ref.set({uppercase}, {merge: true});
});

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1