Edited at

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 'fire

base
'
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は楽ですね。

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