2018-08-18に更新

GAE+NuxtのSSRでFirestoreを使う

App Engineの標準環境でNuxtを使って無料SSR を先日やってみたので、今度はFirebaseのCloud Firestoreでデータの保存を試してみました。

ちなみにGAEのスタンダード環境ではNode8が動くため、ローカルでも全てNode8で動かす必要があります。

Firebaseの初期設定

plugins/firebase.jsに下記のように設定を保存します。

import * as firebase from "firebase";  
require("firebase/firestore");  

if (!firebase.apps.length) {  
  const config = {  
    apiKey: "your firebase api key",  
    authDomain: "your firebase auth domain",  
    databaseURL: "your firebase database url",  
    projectId: "your google cloud platform project id",  
    storageBucket: "your google cloud platform storage bucket",  
    messagingSenderId: "your firebase messaging sender id"  
  };  
  firebase.initializeApp(config);  
}  

firebase.firestore(); // もしかしたら要らないかも  

そしてnuxt.config.jsで上記を読み込むようにしておきます。

  plugins: ["~/plugins/firebase.js"],  

これでFirebaseのライブラリがNuxt上で利用できるようになります。

Firestoreへのデータ追加&取得

元々あるindex.vueを下記のように修正し、データの一覧を追加してボタンを押すとデータを登録できるようにした最小のサンプルを作ってみました。(関係ないところは削っています)

テンプレート

テンプレートは単にデータを表示しているだけで特筆するところは無いです。

<template>  
  <section class="container">  
    <div>  
      <div v-for="text in texts" :key="text.id">  
        {{ text.body }}  
      </div>  
      <input type="text" v-model="textInput">  
      <button type="button" @click="add">add</button>  
    </div>  
  </section>  
</template>  

スクリプト

初期化

import db from "../lib/db";  

DBを簡単に使える様にインポートしてすぐ使えるようにしています。これは別に必ず作らなければならないわけではありません。中身は単にdbを初期化して取ってきているだけです。

import * as firebase from "firebase";  
export default firebase.firestore();  

データをFirestoreから取得してくる

ページを読み込むと、まずFirestoreからデータを取ってきて一覧します。

async function getTexts() {  
  return new Promise(callback => {  
    let texts = [];  
    db  
      .collection("texts")  
      .get()  
      .then(query => {  
        query.forEach(doc => {  
          texts.push(doc.data());  
        });  
        callback(texts);  
      });  
  });  
}  

export default {  
  data() {  
    return {  
      texts: [],  
      textInput: ""  
    };  
  },  
  async asyncData({ params }) {  
    return { texts: await getTexts() };  
  }  
}  

データの初期化にmountedを使うことは多いと思いますが、これはサーバーサイドレンダリングでは動作しないため、代わりにasyncDatafetchを使う必要があります。asyncDataは下記URLに使い方が載っていますが、async/awaitを使ったり、Promiseやcallback形式など自由に選べるようです。

非同期なデータ - Nuxt.js

あとこの中ではthisが使えないため、仕方なく適当にクラスの外にfunctionを定義してそれを呼び出しています。

あ、あとasyncDataはコンポーネントでは使えないため、今回はページ上で実行しています。実際の開発の際もコンポーネントで値を使いたい場合はプロパティで渡すか、storeを使うかになると思います。

データをFirestoreに追加する

あとは追加ボタンをクリックした時の処理を追加します。

  methods: {  
    add() {  
      db  
        .collection("texts")  
        .add({  
          body: this.textInput  
        })  
        .then(docRef => {  
          this.textInput = "";  
          return getTexts();  
        })  
        .then(texts => (this.texts = texts));  
    }  
  }  

追加してとりあえず先程の一覧取得処理を実行しているだけです。

これでFirestoreにデータが保存され、画面上にも表示されます。Firebase Consoleのデータ一覧でも確認できます。

サーバーサイドレンダリングされているか確認

Google App Engineで動作させればサーバーサイドレンダリングされますので、一度ページをリロードして確認すればソース上に登録した文字列が存在するのが確認できると思います。(間違ってmountedで処理しているとSSRされません)

FIrebaseだとデプロイもあっというまでサーバー側の処理とか何も気にしないでいいので楽ですね!

あとはFirestoreにはリアルタイム アップデートの機能もありますので、一覧取得とかは頻繁に更新されるのであればそっちでやってみるのも良いかもしれません。


dala00

Crieitの開発者です。 主にLAMPで開発しているSEです(在宅&常駐)。大体10年程。 業務依頼、同業種の方からのコンタクトなどお気軽にご連絡ください。 業務経験有:PHP, MySQL, CakePHP3, Laravel5, JavaScript 趣味:Elixir, Phoenix, Node, Vue等色々

Crieitはαバージョンで開発中です。進捗は公式Twitterアカウントをフォローして確認してください。 興味がある方は是非記事の投稿もお願いします! どんな軽い内容でも嬉しいです。
関連記事

コメント