こちらは Firebase Advent Calendar 2017 - Qiita 23日目の記事です。

先日SafariがPreview版でServiceWorkerを実装したという話もあり、2018年はServiceWorker,それに伴うPWA関連の技術がより注目されそうですね。 私個人的にも注目の技術の一つとしてキャッチアップしておかないとと最近強く感じてます。

前回はNuxt.jsでPWAを設定する方法を紹介させてもらいました。 PWAをNuxt.jsで簡単に体験する

今回はさらにDBを使って動的コンテンツをPWAする方法を検証してみたいと思います。 前回のプロジェクトをそのまま使用する前提で話を進めていきますので、プロジェクトの作成等は上記の記事を参考にしてください。

Nuxt.jsについてはこちらを参考に。

Vue.jsで作られたフレームワーク「Nuxt.js」でできること

完成イメージ

FireStoreに保存された画像のURLのリストを元に、Firebaseのホスティング上にレンダリング、さらにそのコンテンツをキャッシュさせてオフラインでも閲覧できるようにします。

画像のURLに関しては、外部サイトの画像のキャッシュを実現するため、tumblrの画像URLを使用してみます。

下記のようにオフラインでも画像が表示されれば完成です。

Firebase用の環境を設定する

Firebaseのcliをインストールする

1
$ yarn global add firebase

次にFirebase cli上でログインします。

1
$ firebase login

対話的にログイン情報を求められるので、入力したらcliの設定は完了です。

モジュールインストール

まずは、Nuxt.jsとFirebaseの連携を簡単にするモジュールをインストールします。

1
$ yarn add nuxt-firebase

こちらのモジュールは、Nuxt.jsのpageコンポネント上でapp.$firebase(), this.$firebase()のような形でFirebaseのインスタンスを呼び出せるものとなります。

Firebaseには設定が必要ですので、webコンソールからアプリケーションを作成後、下記の設定を取得してください。

こちらのjsオブジェクトをnuxt.config.jsに貼り付けます。

1
2
3
4
5
6
7
8
  env: {
    apiKey: '',
    authDomain: '',
    databaseURL: '',
    projectId: '',
    storageBucket: '',
    messagingSenderId: ''
  },

Firebaseに必要なファイルの追加

今回はFirebaseの機能のうち

  • ホスティング用ストレージ
  • FireStore

を使用したいと思うので、そこに必要な設定ファイルだけ追加します

firebase.json

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
{
  "firestore": {
    "rules": "firestore.rules",
    "indexes": "firestore.indexes.json"
  },
  "hosting": {
    "public": "dist",
    "ignore": [
      "firebase.json",
      "**/.*",
      "**/node_modules/**"
    ]
  },
  "storage": {
    "rules": "storage.rules"
  }
}

firestore.indexes.json

1
2
3
{
  "indexes": []
}

firestore.rules

1
2
3
4
5
6
7
service cloud.firestore {
  match /databases/{database}/documents {
    match /{document=**} {
      allow read, write;
    }
  }
}

storage.rules

1
2
3
4
5
6
7
service firebase.storage {
  match /b/{bucket}/o {
    match /{allPaths=**} {
      allow read, write: if request.auth!=null;
    }
  }
}

設定は以上となります

動的コンテンツを生成する

FireStoreに画像のURLを保存していきます。 まずはDatabaseからFireStoreを選択し、使用可能にします。

次に下記のようにwebコンソール上でデータを追加します。 Valueのところはtumblrから画像URLを取得し、入力します。

Nuxt.jsのpage上でFirebaseのデータを取得できるようにする

FireStoreではRealtimeDatabaseと同様、オフラインでのキャッシュに対応しています。 app.$firebase.firestore().enablePersistence()という処理を実際の取得処理の前に記述しましょう。

collection(‘image’).get()でデータを取得できるのですが、内部構造は下記のようになっているので、その形で<template>タグ内で画像をよびだします

1
2
3
4
5
6
7
images:
  docs:
    - data():
      - url: "画像URL"
    - data():
      - url: "画像URL"
    ...
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
 export default {
   components: {
     Logo
+  },
+  async asyncData ({app}) {
+    try {
+      await app.$firebase.firestore().enablePersistence()
+      const images = await app.$firebase.firestore().collection('images').limit(5).get()
+      return {
+        images: images.docs
+      }
+    } catch (err) {
+      console.log(err)
+    }
   }
 }
 </script>

<temlpate>

1
2
3
4
5
6
      <div>
        <img
          v-for="image in images"
          :src="image.data().url"
        />
      </div>

本番にデプロイする

nuxt build --spa/distディレクトリにデプロイ用のファイルを生成したのち、firebase deployコマンドでデプロイします。

デプロイが完了すると、https://<projectId>.firebaseapp.comにアプリケーションが反映されます。

デベロッパーツールでオフラインにしても同じように画像が表示されることが確認できるかと思います。

まとめ

Firebase, Nuxt.jsを使うことで、動的コンテンツのPWA化も簡単にできることが確認できました。