How To Create A Mobile App Using Vite, Vue, and Ionic Capacitor - Adding Firebase & Firebase Emulator To Project
Tags: firebase, vue, ionic, javascript
Published: 2023-03-15 17:42:59

Welcome to our blog post on [Firebase Emulator]( https://firebase.google.com/docs/emulator-suite/install_and_configure) integration with your Vite, Vue project! This post is a companion to our video on the same topic, which you can find linked below. 

{% youtube YUbh1zTJW3A %}

If you've been struggling with testing and iterating on your [Firebase](https://firebase.google.com/docs) project, constantly having to push to a live environment just to see your changes, then you're in luck! In this post, we'll show you how to integrate Firebase Emulator into your Vite, Vue project using [Ionic Capacitor](https://capacitorjs.com/), giving you the power to test, iterate and reset your data, all from the comfort of your local machine.

We'll walk you through the process step-by-step, providing terminal commands and source code to support the video, so you can follow along and see exactly how it's done. But that's not all - this post is part of an ongoing series on Firebase integration with Vite, Vue project. In upcoming videos, we'll show you how to fully integrate Firebase with [VueFire](https://vuefire.vuejs.org/), a library that provides seamless integration of Firebase with Vue.js applications.

So, if you're ready to take your [Firebase](https://firebase.google.com/docs) project to the next level and streamline your development process, be sure to check out our video and follow along with this post!

### Install NPM Packages
```
npm install -g firebase-tools
npm install firebase
```

### Login To Your Firebase Account
```
firebase login
```

### Initialize Local Firebase Emulator
```
firebase init
```

#### Sample Output
```
aaronksaunders@Aarons1ProM1Pro vite-vue-cap % firebase init                              

     ######## #### ########  ######## ########     ###     ######  ########
     ##        ##  ##     ## ##       ##     ##  ##   ##  ##       ##
     ######    ##  ########  ######   ########  #########  ######  ######
     ##        ##  ##    ##  ##       ##     ## ##     ##       ## ##
     ##       #### ##     ## ######## ########  ##     ##  ######  ########

You're about to initialize a Firebase project in this directory:

  /Users/aaronksaunders/develop/projects/vite-vue-cap

? Which Firebase features do you want to set up for this directory? Press Space to select 
features, then Enter to confirm your choices. Emulators: Set up local emulators for Firebase 
products

=== Project Setup

First, let's associate this project directory with a Firebase project.
You can create multiple project aliases by running firebase use --add, 
but for now we'll just set up a default project.

? Please select an option: Create a new project
i  If you want to create a project in a Google Cloud organization or folder, please use "firebase projects:create" instead, and return to this command when you've created the project.
? Please specify a unique project id (warning: cannot be modified afterward) [6-30 characters]:
 testem1
? What would you like to call your project? (defaults to your project ID) 
✔ Creating Google Cloud Platform project
✔ Adding Firebase resources to Google Cloud Platform project

🎉🎉🎉 Your Firebase project is ready! 🎉🎉🎉

Project information:
   - Project ID: testem1
   - Project Name: testem1

Firebase console is available at
https://console.firebase.google.com/project/testem1/overview
i  Using project testem1 (testem1)

=== Emulators Setup
? Which Firebase emulators do you want to set up? Press Space to select emulators, then Enter to 
confirm your choices. Authentication Emulator, Firestore Emulator
? Which port do you want to use for the auth emulator? 9099
? Which port do you want to use for the firestore emulator? 8080
? Would you like to enable the Emulator UI? Yes
? Which port do you want to use for the Emulator UI (leave empty to use any available port)? 
? Would you like to download the emulators now? Yes
i  ui: downloading ui-v1.11.4.zip...

i  Writing configuration info to firebase.json...
i  Writing project information to .firebaserc...

✔  Firebase initialization complete!
```
### Start The Emulator
```
firebase emulators:start
```

#### Sample Output
```
aaronksaunders@Aarons1ProM1Pro vite-vue-cap % firebase emulators:start
i  emulators: Starting emulators: auth, firestore
⚠  firestore: Did not find a Cloud Firestore rules file specified in a firebase.json config file.
⚠  firestore: The emulator will default to allowing all reads and writes. Learn more about this option: https://firebase.google.com/docs/emulator-suite/install_and_configure#security_rules_configuration.
i  firestore: Firestore Emulator logging to firestore-debug.log
✔  firestore: Firestore Emulator UI websocket is running on 9150.
i  ui: downloading ui-v1.11.4.zip...
Progress: =========================================================================> (100% of 4MB)
i  ui: Removing outdated emulator files: ui-v1.6.5
i  ui: Removing outdated emulator files: ui-v1.6.5.zip
i  ui: Emulator UI logging to ui-debug.log

┌─────────────────────────────────────────────────────────────┐
│ ✔  All emulators ready! It is now safe to connect your app. │
│ i  View Emulator UI at http://127.0.0.1:4000/               │
└─────────────────────────────────────────────────────────────┘

┌────────────────┬────────────────┬─────────────────────────────────┐
│ Emulator       │ Host:Port      │ View in Emulator UI             │
├────────────────┼────────────────┼─────────────────────────────────┤
│ Authentication │ 127.0.0.1:9099 │ http://127.0.0.1:4000/auth      │
├────────────────┼────────────────┼─────────────────────────────────┤
│ Firestore      │ 127.0.0.1:8080 │ http://127.0.0.1:4000/firestore │
└────────────────┴────────────────┴─────────────────────────────────┘
  Emulator Hub running at 127.0.0.1:4400
  Other reserved ports: 4500, 9150

Issues? Report them at https://github.com/firebase/firebase-tools/issues and attach the *-debug.log files.
```

### The Code From Video
```javascript
import { createApp } from "vue";
import "./style.css";
import App from "./App.vue";
import { IonicVue } from "@ionic/vue";

/* Core CSS required for Ionic components to work properly */
import "@ionic/vue/css/core.css";

/* Basic CSS for apps built with Ionic */
import "@ionic/vue/css/normalize.css";
import "@ionic/vue/css/structure.css";
import "@ionic/vue/css/typography.css";

/* Optional CSS utils that can be commented out */
import "@ionic/vue/css/padding.css";
import "@ionic/vue/css/float-elements.css";
import "@ionic/vue/css/text-alignment.css";
import "@ionic/vue/css/text-transformation.css";
import "@ionic/vue/css/flex-utils.css";
import "@ionic/vue/css/display.css";

/* Theme variables */
// import './theme/variables.css';

import router from "./router";
import { initializeApp } from "firebase/app";
import {
  getFirestore,
  collection,
  addDoc,
  connectFirestoreEmulator,
  serverTimestamp,
  query,
  getDocs,
  orderBy,
} from "firebase/firestore";

const firebaseApp = initializeApp({
  projectId: "testem1",
});

console.log("firebaseApp", firebaseApp);

// used for the firestore
export const db = getFirestore(firebaseApp);
console.log("firestore database", db);

// connect the application to the emulator
if (location.hostname === "localhost") {
  // Point to the Storage emulator running on localhost.
  connectFirestoreEmulator(db, "localhost", 8080);
}

(async () => {
  try {
    // write a document to database...
    const docRef = await addDoc(collection(db, "stuff"), {
      name: "aaron",
      created_at: serverTimestamp(),
    });
    console.log("new document", docRef);

    // get all of the documents
    const queryResult = await getDocs(
      query(collection(db, "stuff"), orderBy("created_at", "asc"))
    );

    // display to console
    const dataArray = queryResult.docs.map((d) => {
      return { name: d.data().name, when: d.data().created_at.toDate() };
    });
    console.log("queryResult", dataArray);
  } catch (e) {
    console.log(e);
  }
})();

const app = createApp(App).use(IonicVue).use(router);

router.isReady().then(() => {
  app.mount("#app");
});
```