5
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

Nuxt.jsとFirebase RealtimeDatabase CloudFirestore でBaaS開発入門

Last updated at Posted at 2019-12-04

福岡から世界中の"むずかしい"を簡単にする株式会社diffeasyCTOの西@_takeshi_24です。

この記事はアドベントカレンダー「diffeasyCTO西の24(にし)日連続投稿チャレンジ Advent Calendar 2019」の5日目の記事です。

この記事は「Nuxt.jsとFirebaseとCloudFunctionsでWebアプリ開発」シリーズとして、連載していきます。
Nuxt.jsとFirebaseなどを使ってWebアプリケーション開発にチャレンジしたい方、是非Qiitaアカウントかtwitterをフォローしていただき、ツッコミやいいね!お願いします!

はじめに

こちらの記事は、「Nuxt.jsとFirebaseとCloudFunctionsでWebアプリ開発」シリーズとして連載していますので、過去の記事もご覧ください。

##RealtimeDatabaseとCloudFirestore
FirebaseのデータベースにはRealtimeDatabaseとCloudFirestoreの2種類があります。
データベースを選択: Cloud Firestore または Realtime Databaseにも解説がありますが、それぞれ特徴を簡単に説明すると、

  • RealtimeDatabase:レイテンシが低く、シンプルなリアルタイム処理に向いている。
  • CloudFirestore:RealtimeDatabaseよりもクエリが柔軟で高速。

といった感じです。

##Nuxt.jsでRealtimeDatabase
以前の記事ではvuexfireというパッケージを使っていましたが、最近はあまりメンテナンスされていないようです。
スクリーンショット 2019-12-03 22.50.29.png

vuexfireを使わなくても、簡単にNuxt.jsからFirebaseのRealtimeDatabase、Firestoreを扱えますので、今回はその方法を説明します。

まずはFirebaseのRealtimeDatabaseにデータを書き込み、リアルタイムで表示します。

messagesというコレクションにmessageTextという値を追加します。

1./pages/messages/index.vueを以下の内容で作成します。

/pages/messages/index.vue
<template>
  <section class="container">
    <v-row>
      <v-col>
        <v-text-field v-model="messageText"></v-text-field>
      </v-col>
      <v-col>
        <v-btn @click="addMessage">投稿</v-btn>
      </v-col>
    </v-row>
    <v-row v-for="(message, key, index) in messages" :key="index">
      <v-col>
        <p>
          {{ message.messageText }}
        </p>
      </v-col>
    </v-row>
  </section>
</template>
<script>
import firebase from "firebase";

export default {
  data() {
    return {
      messages: [],
      messageText: ""
    };
  },
  mounted() {
    this.initMessages();
  },
  methods: {
    initMessages() {
      firebase
        .database()
        .ref("messages")
        .on("child_added", snapshot => {
          this.messages.unshift(snapshot.val());
        });
    },
    addMessage() {
      firebase
        .database()
        .ref("messages")
        .push({ messageText: this.messageText });
      this.messageText = "";
    }
  }
};
</script>

2.yarn run devで起動して、テキストにメッセージを入力し、「投稿」ボタンをクリックします。

3.Permission deniedのエラーが返ってきます。RealtimeDatabaseに対する書き込み権限がないためです。ログインユーザーのみ、RealtimeDatabaseの読み込み書き込みができるように、firebase.jsonと同じ場所にあるdatabase.rules.jsonファイルを修正します。

database.rules.json
{
  "rules": {
    "messages": {
      ".read": "auth != null",
      ".write": "auth != null"
    }
  }
}

4.DBルールをデプロイします。

$ firebase deploy --only database

5.もう一度テキストにメッセージを入力し、「投稿」ボタンをクリックします。今度は投稿できて、投稿した内容がリアルタイムで表示されました。
スクリーンショット 2019-11-30 17.28.03.png

##Nuxt.jsでCloudFirestore
次に、Firestoreのusersコレクションにログイン中のユーザー情報を登録処理を作ります。

1./pages/current_user/index.vueを以下の内容で作成する。

/pages/current_user/index.v
<template>
  <section class="container">
    <v-row>
      <v-col>
        <v-text-field v-model="familyName" placeholder="姓"></v-text-field>
      </v-col>
      <v-col>
        <v-text-field v-model="firstName" placeholder="名"></v-text-field>
      </v-col>
      <v-col>
        <v-btn @click="updateUser">更新</v-btn>
      </v-col>
    </v-row>
  </section>
</template>
<script>
import firebase from "firebase";
const db = firebase.firestore();

export default {
  data() {
    return {
      uid: "",
      firstName: "",
      familyName: ""
    };
  },
  created() {
    firebase.auth().onAuthStateChanged(user => {
      this.uid = user.uid;
      this.getUser();
    });
  },
  methods: {
    async getUser() {
      const userRef = db.collection("users").doc(this.uid);
      const userDoc = await userRef.get();
      if (userDoc.exists) {
        this.firstName = userDoc.data().firstName;
        this.familyName = userDoc.data().familyName;
      }
    },
    updateUser() {
      db.collection("users")
        .doc(this.uid)
        .set({
          firstName: this.firstName,
          familyName: this.familyName
        });
    }
  }
};
</script>

firebaseの認証情報が非同期で取得されますので、firebase.auth().onAuthStateChangedでログインユーザーのuidを取得します。

getUser()でログインユーザーの情報を取得して、updateUser()でログインユーザーの情報を更新しています。

通常のサービスであれば、セッション情報などを使って、サーバーサイドでUIDを取得すれば安全ですが、BaaSのFirebaseをNuxt.jsから呼ぶ場合、クライアントからUIDをサーバーに渡す必要があります。

クライアント側でUIDを渡しているので、当然改竄しようと思えば、改竄可能です。
他人のUIDのデータを改竄されたら問題なので、Firestore側でデータ更新ルールを使ってデータを保護する必要があります。

2.firebase.jsonと同じ場所にあるfirestore.rulesファイルを修正します。

service cloud.firestore {
  match /databases/{database}/documents {
    match /users/{userId} {
      allow read, update, delete: if request.auth.uid == userId;
      allow create: if request.auth.uid != null;
    }
  }
}

usersコレクションのuserIdとログインユーザーのUIDが一致していれば、読み込み、更新、削除可能で、ログイン中であれば登録できるルールに設定します。

なお、今回getUser()でcreated時にusersコレクションのデータを取得していますが、リアルタイムで取得するには、onSnapshotを利用すると、リアルタイムで取得できます。

データの更新処理には、データ一貫性を保持する必要があり、トランザクションは必須です。
Firebaseのトランザクションについてはまた今後の記事で紹介します。

##最後に
この記事は「Nuxt.jsとFirebaseとCloudFunctionsでWebアプリ開発」シリーズとして、連載していきます。
続きはアドベントカレンダー「diffeasyCTO西の24(にし)日連続投稿チャレンジ Advent Calendar 2019」に掲載していきます。

Nuxt.jsとFirebaseなどを使ってWebアプリケーション開発にチャレンジしたい方、是非Qiitaアカウントかtwitterをフォローしていただき、ツッコミやいいね!お願いします!

#advent_24のハッシュタグでフィードバックいただけると嬉しいです!

5
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?