How to build and deploy a Vue.js CRUD app with Cloud Firestore and Firebase
Tags: firebase, vue, tutorial, webdev
Published: 2020-05-13 13:24:29

---
title: How to build and deploy a Vue.js CRUD app with Cloud Firestore and Firebase
published: true
date: 2020-04-17 17:30:22 UTC
tags: firebase,vue,tutorial,webdev
canonical_url: https://blog.logrocket.com/how-to-build-and-deploy-a-vue-js-crud-app-with-cloud-firestore-and-firebase/
cover_image: https://dev-to-uploads.s3.amazonaws.com/i/g5iysh3ktnf04s52k7oh.png
---
**Written by [Timothy Olakeke](https://blog.logrocket.com/author/timothyolaleke/)**✏️

Frontend engineers today can easily build interfaces and implement their functionalities without the headache of integrating a backend or application programming interface (API). In this tutorial, we’ll demonstrate how to build a Vue.js application with create, read, update, delete (CRUD) functionalities and store data with Cloud Firestore. If you wish, you can also deploy this application to Firebase Hosting.

[Firebase](https://firebase.google.com/) is a backend-as-a-service (BaaS) offering by Google that features databases, an ML kit, cloud functions, authentication, hosting, cloud storage, and more. Firebase abstracts the complexity of building a robust and scalable backend system, enabling developers to focus on building the client side of applications.

For our CRUD application, we’ll focus on using Cloud Firestore for data storage. [Cloud Firestore](https://firebase.google.com/docs/firestore) is a NoSQL database that stores data in the form of documents, which are arranged into collections and support client- or server-side integration. Cloud Firestore documents contain various fields that can hold any data type and support very fast read or write.

[Vue.js](https://vuejs.org/) is a lightweight framework for building interactive user interfaces and single-page applications. We’ll use a design library called [Element UI](https://element.eleme.io/#/en-US), which provides components to help developers build faster user interfaces.

[![LogRocket Free Trial Banner](https://i0.wp.com/blog.logrocket.com/wp-content/uploads/2017/03/f760c-1gpjapknnuyhu8esa3z0jga.png?resize=1200%2C280&ssl=1)](https://logrocket.com/signup/)

## Prerequisites

To follow along with this tutorial, you’ll need:

- Basic knowledge of [Vue.js](https://vuejs.org/)
- [Node](https://nodejs.org/en/download/) and [NPM](https://www.npmjs.com/get-npm) installed
- A [Google](https://support.google.com/accounts/answer/27441?hl=en) account
- [Firebase tools CLI](https://github.com/firebase/firebase-tools) installed (alternatively, use `npm install -g firebase-tools`)
  - You’ll need to log in with your Google account using `firebase login`
- [Vue.js CLI](https://cli.vuejs.org/) installed (or use `npm install -g @vue/cli`)
  - You can confirm your Vue.js CLI version using `vue --version`

## Firebase setup

To get started with Firebase, create a Firebase project by following the steps below. (Note: Firebase projects are linked to Google Cloud Platform project.)

1. Visit the [Firebase console](https://console.firebase.google.com/u/0/?pli=1) and sign in with your Google account
2. Click “Add Project”
3. Click “Continue” to create the project (we don’t need analytics) ![Firebase Console](https://i0.wp.com/blog.logrocket.com/wp-content/uploads/2020/04/firebase-console.png?resize=720%2C333&ssl=1)
4. Click on the web icon `</>`
5. For the app nickname, enter whatever name you want and click “Next”
6. When your Firebase configuration is displayed, copy the contents within the scripts tag ![Firebase Configuration](https://i0.wp.com/blog.logrocket.com/wp-content/uploads/2020/04/firebase-configuration.jpeg?resize=650%2C705&ssl=1)
7. Click on “Database,” then, under “Cloud Firestore,” click “Create database”
8. Set the [security rules](https://firebase.google.com/docs/rules/get-started) in test mode ![Configuring Security Rules in Firebase](https://i0.wp.com/blog.logrocket.com/wp-content/uploads/2020/04/security-rules-firebase.png?resize=641%2C417&ssl=1)
9. Select a location and click “Next”
10. Create an employees collection and add some random documents (optional) ![Employees Collection With Random Documents in Firebase](https://i1.wp.com/blog.logrocket.com/wp-content/uploads/2020/04/employees-collection-documents-firebase.png?resize=720%2C160&ssl=1)

## Vue setup

Setting up a Vue.js project will create the files and install the dependencies required to build a user interface. Execute the following command.

```jsx
vue create crud-app
```

Configure your Vue.js project on the interactive screen that shows up. Simply select the default (Babel, ESLint) preset, which is the default configuration.

When done, you should see a new `crud-app` directory.

![Vue Project Setup](https://i1.wp.com/blog.logrocket.com/wp-content/uploads/2020/04/vue-project-setup.png?resize=429%2C105&ssl=1)

Change into the `crud-app` directory using `cd crud-app` or open the folder in your code editor.

To set up Element UI within the created Vue.js project using its Vue.js plugin, execute the following command to install Element UI in the `crud-app` directory.

```jsx
vue add element
```

Configure the setup as follows:

1. Select `Fully import`
2. Since you don’t have to overwrite Element’s SCSS variables, input `N`
3. For `locale` **,** select `en`

![Element UI Installation](https://i2.wp.com/blog.logrocket.com/wp-content/uploads/2020/04/element-ui-installation.png?resize=646%2C268&ssl=1)

We’re now done setting up Vue.js and Element UI.

To start the development server, execute the following.

```jsx
npm run serve
```

You should see an output similar to this on your browser:

![Vue Plus Element UI Default Page](https://i0.wp.com/blog.logrocket.com/wp-content/uploads/2020/04/vue-element-ui-default-page.png?resize=639%2C599&ssl=1) ![Source Files](https://i2.wp.com/blog.logrocket.com/wp-content/uploads/2020/04/source-files.png?resize=275%2C392&ssl=1)

## Configure Firebase with Vue.js

Before you can use Cloud Firestore, you need to set up the [Firebase client](https://firebase.google.com/docs/firestore/client/libraries) on the Vue.js project.

Install the Firebase JS client and update your dependencies within the `crud-app` directory.

```jsx
npm install firebase --save
```

Create a new file with the name `firebaseConfig.js` within the `src` directory with similar contents.

```jsx
// src/firebaseConfig.js
import firebase from "firebase";

// Your web app's Firebase configuration
var firebaseConfig = {
  apiKey: "AIzaSyC9J2hIQ1XQFZZZZZZZZZZZZZZZZZ",
  authDomain: "employee-crud-ZZZZZZZZZ.firebaseapp.com",
  databaseURL: "https://employee-crud-ZZZZZZ.firebaseio.com",
  projectId: "employee-crud-XXXXXXXX",
  storageBucket: "employee-crud-ZZZZZ.appspot.com",
  messagingSenderId: "8761301111111",
  appId: "1:87613015171:web:e60ee5139c5ZZZZZZZ"
};

// Initialize Firebase
export default firebase.initializeApp(firebaseConfig);
```

Replace the `firebaseConfig` object with what you copied earlier during the Firebase app setup.

## Cloud Firestore CRUD methods in Vue.js

Let’s review some methods used for individual CRUD operations in the Vue.js app. Below are some truncated snippets to help explain individual methods.

You’ll need to import the initialized Firebase app and create an instance of Cloud Firestore.

```jsx
import firebase from "./firebaseInit";
const db = firebase.firestore();
```

### Create method

The method below creates a new document on the Cloud Firestore collection.

```jsx
    createEmployee(name, date) {
        db.collection("employees")
          .add({ date: date, name: name })
          .then(() => {
            console.log("Document successfully written!");
          })
          .catch((error) => {
            console.error("Error writing document: ", error);
          });
    }
```

The values of `name` and `date` would be saved as a new document within the `employees` collection.

### Read method

This method is used to fetch all documents from the Cloud Firestore collection.

```jsx
    readEmployees() {
      let employeesData = [];
      db.collection("employees")
        .get()
        .then((querySnapshot) => {
          querySnapshot.forEach((doc) => {
           employeesData.push({
              id: doc.id,
              name: doc.data().name,
              date: doc.data().date,
            });
            console.log(doc.id, " => ", doc.data());
          });
          return employeesData
        })
        .catch((error) => {
          console.log("Error getting documents: ", error);
        });
    }
```

This loops through all documents in the Cloud Firestore collection and writes their data, along with `id` **,** to the `employeesData` variable.

### Update method

The update method is used to edit an existing document on the Cloud Firestore collection.

```jsx
    updateEmployee(id, name, date) {
      db.collection("employees")
        .doc(id)
        .update({
          name: name,
          date: date,
        })
        .then(() => {
          console.log("Document successfully updated!");
        })
        .catch((error) => {
          console.error("Error updating document: ", error);
        });
    }
```

The document with the passed `id` will be updated on the Cloud Firestore collection with the new values for `name` and `date` as passed during the method call.

### Delete method

The delete method erases a document that exists on the Cloud Firestore collection.

```jsx
    deleteEmployee(id) {
      db.collection("employees")
        .doc(id)
        .delete()
        .then(() => {
          console.log("Document successfully deleted!");
        })
        .catch((error) => {
          console.error("Error removing document: ", error);
        });
    }
```

The document with the passed **id** will be deleted on the Cloud Firestore collection.

## Detailed source code

Vue.js uses single-file components, which allows you to build an entire user interface, including the layout, functionalities, and styles, in one .vue file.

For this tutorial, you’ll only need to modify the `App.vue` file.

Element UI provides a lot of reusable components, which makes building interfaces much faster. For our purposes, we’ll use a basic data table to list all the documents coming from the database.

A pop-over input is used to create and edit documents, while a button is used to trigger deletion.

```jsx
<!-- src/App.vue -->
<template>
  <div>
    <el-popover
      placement="bottom"
      title="New Employee"
      width="200"
      trigger="click"
    >
      <el-input
        placeholder="John Doe"
        v-model="name"
        @blur="createEmployee(name, date)"
      ></el-input>
      <el-button round slot="reference" type="success"
        >Add New Employee</el-button
      >
    </el-popover>
    <el-table
      :data="
        employeesData.filter(
          (data) =>
            !search || data.name.toLowerCase().includes(search.toLowerCase())
        )
      "
      style="width: 100%;"
    >
      <el-table-column label="Date" prop="date"> </el-table-column>
      <el-table-column label="Name" prop="name"> </el-table-column>
      <el-table-column align="right">
        <template slot="header" :slot-scope="scope">
          <el-input v-model="search" size="mini" placeholder="Type to search" />
        </template>
        <template slot-scope="scope">
          <el-popover
            placement="bottom"
            title="Edit Employee"
            width="200"
            trigger="click"
          >
            <el-input
              placeholder="John Doe"
              v-model="scope.row.name"
              @blur="updateEmployee(scope.row.id, scope.row.name, date)"
            ></el-input>
            <el-button size="mini" slot="reference">Edit</el-button>
          </el-popover>
          <el-button
            size="mini"
            type="danger"
            @click="deleteEmployee(scope.row.id)"
            >Delete</el-button
          >
        </template>
      </el-table-column>
    </el-table>
  </div>
</template>
```

As explained earlier, our functions are all within the `methods()` section. The variables in use are also listed in the `data()`. Since we want to read all the documents once the application loads, we called the `readEmployees()` methods inside the `mounted()` lifecycle hook.

```jsx
<!-- src/App.vue -->
<script>
import firebase from "./firebaseInit";
const db = firebase.firestore();
export default {
  data() {
    return {
      name: "",
      date: new Date().toISOString().slice(0, 10),
      employeesData: [],
      search: "",
    };
  },
  methods: {
    createEmployee(name, date) {
      if (name != "") {
        db.collection("employees")
          .add({ date: date, name: name })
          .then(() => {
            console.log("Document successfully written!");
            this.readEmployees();
          })
          .catch((error) => {
            console.error("Error writing document: ", error);
          });
        this.name = "";
      }
    },
    readEmployees() {
      this.employeesData = [];
      db.collection("employees")
        .get()
        .then((querySnapshot) => {
          querySnapshot.forEach((doc) => {
            this.employeesData.push({
              id: doc.id,
              name: doc.data().name,
              date: doc.data().date,
            });
            console.log(doc.id, " => ", doc.data());
          });
        })
        .catch((error) => {
          console.log("Error getting documents: ", error);
        });
    },
    updateEmployee(id, name, date) {
      db.collection("employees")
        .doc(id)
        .update({
          name: name,
          date: date,
        })
        .then(() => {
          console.log("Document successfully updated!");
          this.readEmployees();
        })
        .catch((error) => {
          // The document probably doesn't exist.
          console.error("Error updating document: ", error);
        });
    },
    deleteEmployee(id) {
      db.collection("employees")
        .doc(id)
        .delete()
        .then(() => {
          console.log("Document successfully deleted!");
          this.readEmployees();
        })
        .catch((error) => {
          console.error("Error removing document: ", error);
        });
    },
  },
  mounted() {
    this.readEmployees();
  },
};
</script>
```

## Deploying the application

Firebase allows you to deploy static files. But first, you must build your assets.

Within the `crud-app` directory, run the following command.

```jsx
npm run build && cd dist
```

Next, initialize Firebase and complete the following steps.

```jsx
firebase init
```

1. Define “hosting” as the Firebase CLI feature you want to set up for the folder
2. For the project setup, select “Use an existing project option”
3. Navigate to and select the project created earlier
4. Set the public directory as: `.`
5. For “Configure as a single-page app (rewrite all urls to /index.html),” choose “Yes”
6. For “File ./index.html already exists. Overwrite?” select “No”

To deploy, execute the following command.

```jsx
firebase deploy
```

![Firebase Hosting Output](https://i1.wp.com/blog.logrocket.com/wp-content/uploads/2020/04/firebase-hosting-output.png?resize=720%2C487&ssl=1)

## Conclusion

You should now have the basic tools you need to build a simple application using Vue.js for the client side and Firebase for data storage and hosting. You can find the full source code on [GitHub](https://github.com/Timtech4u/employee-crud) and also access a [demo of the app](https://employee-crud-app-a3a32.web.app/).

To learn more, check out the following resources.

- [Vue.js guide](https://vuejs.org/v2/guide/)
- [Element UI library](https://element.eleme.io/)
- [Firebase documentation](https://firebase.google.com/docs/)

* * *
## Experience your Vue apps exactly how a user does 

Debugging Vue.js applications can be difficult, especially when there are dozens, if not hundreds of mutations during a user session. If you’re interested in monitoring and tracking Vue mutations for all of your users in production, [try LogRocket.](https://www2.logrocket.com/vue-performance-monitoring)

![Alt Text](https://thepracticaldev.s3.amazonaws.com/i/t4ni6gomxqbkbxygmco0.png)

[LogRocket](https://www2.logrocket.com/vue-performance-monitoring) is like a DVR for web apps, recording literally everything that happens in your Vue apps including network requests, JavaScript errors, performance problems, and much more. Instead of guessing why problems happen, you can aggregate and report on what state your application was in when an issue occurred.

The LogRocket Vuex plugin logs Vuex mutations to the LogRocket console, giving you context around what led to an error, and what state the application was in when an issue occurred.

Modernize how you debug your Vue apps - [Start monitoring for free.](https://www2.logrocket.com/vue-performance-monitoring)
* * *

The post [How to build and deploy a Vue.js CRUD app with Cloud Firestore and Firebase](https://blog.logrocket.com/how-to-build-and-deploy-a-vue-js-crud-app-with-cloud-firestore-and-firebase/) appeared first on [LogRocket Blog](https://blog.logrocket.com).