Help us understand the problem. What is going on with this article?

VuexFireでNuxt.jsアプリに一瞬でFirestoreを導入する

今回のチュートリアルではNuxt.jsを使っていますが、全部フロントエンドで動いているのでVue.jsアプリでも同様に動きます。

TL;DR

サンプルコードはGithubにあります。
VuexFireを使ってNuxt.jsアプリでFirestoreからデータを取得しページに表示させます。また、ページ上のフォームからFirestoreにデータを追加します。

はじめに

前回の記事でVuex.jsとFirebaseのCloud Functionsを使ってSSRアプリを作ってみました。
そのアプリをベースに、今回はVuexFireを使ってFirestoreを導入してみます。
FirestoreはFirebaseの提供するNoSQLデータベースです。現在はβ版ですが、今後Firebase Realtime Databaseに代わりFirebaseのデータベースサービスになっていくようです。

Step 1: Firestore でコレクションを作ってみましょう

コレクションはRDBで言うところのテーブルです。ちなみにドキュメントはRDBのレコードに相当します。

作成するものは以下の通りです。
コレクション:users
ドキュメント:users: { name: "test", email: "test@test.com" }

Cloud Firestore with Vue.jsで簡単なメモアプリを実装する by @rubytomato@githubFirebaseにプロジェクトを作成する にとても丁寧に説明されていたので、そちらを参考にして作ってみてください。

Step 2: パッケージをインストールしてみましょう

私のFirebaseプロジェクト構成は以下の通りです。Nuxt.jsのプロジェクトはsrcの中にあります。

<proj>
L src
  L plugins
  L components
  L package.json
  L ...
L functions
L public

srcに移動してfirebasevuexfireをインストールします。

cd src/ && yarn add firebase vuexfire@next

Step 3: コンフィグファイルを作成してみましょう

serviceAccountKey.jsonファイルを作成します。今回は<proj>フォルダ内に作成します。

<proj>フォルダに移動して、ファイルを作成しましょう

cd ../ && vi serviceAccountKey.json

serviceAccountKey.json
{
  "apiKey": "<API_KEY>",
  "authDomain": "<PROJECT_ID>.firebaseapp.com",
  "databaseURL": "https://<DATABASE_NAME>.firebaseio.com",
  "projectId": "<PROJECT_ID>",
  "storageBucket": "<BUCKET>.appspot.com",
  "messagingSenderId": "<SENDER_ID>"
}

API_KEYなどの情報は https://console.firebase.google.com/u/0/project/プロジェクト名/settings/general/ で確認することができます。

Step 4: firebaseプラグインを作ってみましょう

srcフォルダに移動して、firebase.jspluginsフォルダに作成します。

cd src/ && vi plugins/firebase.js

plugins/firebase.js
import firebase from 'firebase'
import 'firebase/firestore'
const serviceAccount = require('~/../serviceAccountKey.json')

firebase.initializeApp({ ...serviceAccount })
const db = firebase.firestore()
const settings = { timestampsInSnapshots: true }
db.settings(settings)
export { db }

コンフィグファイルを元にfirebaseをイニシャライズし、dbをエクスポートしています。
settingsを省略したところ、Browserのコンソールで追加するよう警告されました。

Step 5: プラグインをNuxt.jsで使えるように設定ファイルを編集しましょう

srcフォルダにいることを確認してください。nuxt.config.jsを編集してpluginを使えるよう設定します。

vi nuxt.config.js

nuxt.config.js
module.exports = {
  ...
  plugins: ['~/plugins/firebase'],
  ...
}

Step 6: Vuex用のstoreファイルを作成してみましょう

srcフォルダにいることを確認してください。storeフォルダの中にindex.jsを作成して編集していきます。

vi store/index.js

store/index.js
import Vuex from 'vuex'
import { firebaseMutations, firebaseAction } from 'vuexfire'

const createStore = () => {
  return new Vuex.Store({
    state: {
      users: [],
    },
    mutations: {
      ...firebaseMutations
    },
    actions: {
      setUsersRef: firebaseAction(({ bindFirebaseRef }, ref) => {
        bindFirebaseRef('users', ref)
      })
    },
    getters: {
      getUsers: (state) => {
        return state.users
      },
    },
  })
}

export default createStore

ここで特別なところは以下のvuexfireを使っているところです。
- import { firebaseMutations, firebaseAction } from 'vuexfire'
- mutations
- actions.setUsersRef

でもたったこれだけです。

Step 7: ページに表示させてみましょう

srcフォルダにいることを確認してください。pages/users.vueを編集して、Step 1で作ったコレクションを表示させてみましょう。

pages/users.vue
<template>
  <div>
    <h1>firestore contents here</h1>
    <ul>
      <li v-for="(user, userIdx) in users" :key="userIdx">
        <ul>
          <li>name: {{ user.name }}</li>
          <li>email: {{ user.email }}</li>
        </ul>
      </li>
    </ul>
  </div>
</template>

<script>
import { db } from '~/plugins/firebase.js'
import { mapGetters } from 'vuex'

export default {
  created: function () {
    this.$store.dispatch('setUsersRef', db.collection('users'))
  },
  computed: {
    ...mapGetters({ users: 'getUsers' })
  },
}
</script>

<style>
</style>

createdでFirestoreのusersをバインドし、computedにてVuex経由でusersをフェッチしてテンプレートで表示させています。

srcフォルダ内でyarn devを実行してみてください。サーバーが無事に起動したら http://localhost:3000/users をブラウザで開いてみてください。無事にコレクションが表示されましたか?おめでとうございます!
前回の記事から続けてくださっている場合、エラーが出るかもしれません。このコミットを追加して、再度yarn devを実行してみてください。

Step 8: ページからコレクションを追加してみましょう

pages/users.vueにフォームみたいなものを足してみましょう。

<template>
  <div>
    <h1>firestore contents here</h1>
    <ul>
      <li v-for="(user, userIdx) in users" :key="userIdx">
        <ul>
          <li>name: {{ user.name }}</li>
          <li>email: {{ user.email }}</li>
        </ul>
      </li>
    </ul>
+    <div class="form">
+      <h1>I know, but this is the form!</h1>
+      <div>
+               Name: <input type="text" name="name" v-model="name">
+      </div>
+      <div>
+               email: <input type="text" name="email" v-model="email">
+      </div>
+      <div>
+        <button @click="submit">Submit</button>
+      </div>
+    </div>
  </div>
</template>

<script>
import { db } from '~/plugins/firebase.js'
import { mapGetters } from 'vuex'

export default {
  created: function () {
    this.$store.dispatch('setUsersRef', db.collection('users'))
  },
  computed: {
    ...mapGetters({ users: 'getUsers' })
  },
+  data: function () {
+    return {
+      name: '',
+      email: '',
+    }
+  },
+  methods: {
+    submit: function () {
+      const user = {
+        name: this.name,
+        email: this.email,
+      }
+      const usersRef = db.collection('users')
+      usersRef.add(user)
+      this.name = ''
+      this.email = ''
+    }
+  },
}
</script>

<style>
</style>

const usersRef = db.collection('users')でFirestoreのusersを参照し、そこにuserを追加しています。
実際にフォームに入力してみると、入力値がFirebase, Vuexを経由してフォームの上のリストに追加される様子がわかります。

同様に、Firebase ConsoleをみてみるとFirestoreにもデータが追加されていることがわかります。

おわりに

無事にFirestoreの第一歩が踏み出せたことを祈っています。次のステップとしてはFirestoreのセキュリティ設定などになってくるかと思います。Pros/ConsありますがServerlessは楽ですね。

読んでいただきありがとうございました。

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away