nuxt/firebaseメモ

# nuxt/firebaseメモ

## 概要
[nuxt/firebase](https://firebase.nuxtjs.org/)の開発メモ。
あくまでも自分用のメモなので乱文注意。
firestore, firehosting についても使用する。
内容は頻繁に更新される。

## 手順
### nuxtプロジェクトを作成する
WebStormのプラグインによって導入されたウィザードに従ってNuxtプロジェクトを作成する。

## firebaseをインストールする
```.bash
npm install firebase
```

## @nuxtjs/firebaseをインストールする
```.bash
npm install @nuxtjs/firebase
```

## Nuxtの入力補完プラグイン(@nuxt/types)をインストールする
```.bash
npm install @nuxt/types
```

## nuxt.config.jsの書き換え
### modulesにfirebaseのコンフィグを追記する
nuxt.config.jsonのmoulesにコンフィグを追記する。
またコンフィグ内にserviceとしてfirebaseの利用する機能を記述する。
下記ではauthとfirestoreを使う場合の例。
値は適宜書き換えること。

```nuxt.config.json
modules: [
    [
      '@nuxtjs/firebase',
      {
        config: {
          apiKey: '<apiKey>',
          authDomain: '<authDomain>',
          projectId: '<projectId>',
          storageBucket: '<storageBucket>',
          messagingSenderId: '<messagingSenderId>',
          appId: '<appId>',
          measurementId: '<measurementId>' // この項目は現在は不要なようだ
        },
        services: {
          // Just as example. Can be any other service.
          auth: true,
          firestore: true,
        }
      }
    ]
],
```

### buildの設定を書き換える
このままだとgenerate時に警告がでるのでnuxt.config.jsに次の追記を行う。
(Nuxtとbabelの相性問題のようなもののようだ)

```nuxt.config.js
build: {
    babel: {
      compact: true,
    },
},
```

### modulesに出力先フォルダを指定する(デフォルトからの変更)
Nuxt.jsによるファイル出力先をデフォルトのdistからpublicに変更する。
(publicとするのがfirebaseのデフォルトなので。firebase側の設定を変えてもよいはず)

具体的にはnuxt.config.jsonに次のように追記する。
(場所はどこでも。buildの下、つまり一番下とかで)

```nuxt.config.json
// ファイル出力先
generate: {
  dir: 'public'
},
```

### auth機能利用のための認証情報を追記する
servicesの中にauthの設定を追記する。

```nuxt.config.js
services: {
  auth: {
    persistence: 'local', // default
    initialize: {
      // onAuthStateChangedMutation: 'ON_AUTH_STATE_CHANGED_MUTATION', // 設定の仕方次第では不要?
      onAuthStateChanged: 'onAuthStateChanged',
      subscribeManually: false
    },
    ssr: false, // default
    emulatorPort: 9099,
    emulatorHost: 'http://localhost'
  },
  firestore: true
}
```

### 現在ログイン中のユーザ情報を取得する
次の記述で実現する

```hogehoge.js
this.$fire.auth.currentUser;
```

実際にはこの処理をログイン後に実行しなくてはならないため、次のような使い方をすることになる。

```hogehoge.js
this.$fire.auth.signInWithPopup(provider).then(userCredential => {
  // ログインユーザ情報を取得してuserに代入
  this.user = this.$fire.auth.currentUser; 
  // vuexを使ってるならこうなる
  this.$store.dispatch('onAuthUserChanged', userCredential.user);
}).catch(err => {
  console.error(err);
});
```


## firebaseにログアウト/ログインする
念の為にfirebaseにログイン/ログアウトしておく

```.bash
firebase logout
firebase login
```

## firebaseプロジェクトとして初期化する
```.bash
firebase init
```

プロジェクト名や利用機能などが尋ねられるので適宜答えていく。
hostとstoreとemulator(ローカルでテストできる)が典型的な組合わせになるだろう。

## プロジェクトを出力する(npm run generate)
```.bash
npm run generate
```

## エミュレートする
```.bash
firebase emulators:start
```

localhost:5000で起動するのでアクセスして確かめる。
正常にページが表示されていれば成功。

## デプロイする(firebase hosting)
```
firebase deploy
```

正常に進行すれば Deploy complete! というメッセージとコンソールのURL、ホスト先のURLが表示される。

## forestoreの扱いについて
### コレクションに含まれる全てのドキュメントを取得する(非リアルタイム)
コレクションに含まれる全てのドキュメントリファレンスを取得し、
messageプロパティの内容をコンソールに出力する場合を例示する。

```hogehoge.js
// コレクションリファレンスの取得
const collectionRef = this.$fire.firestore.collection('messages'); 

// collectionRef.get() で コレクションのスナップショットを取得
// スナップショットから全てのドキュメントリファレンスを取得できる(snapshot.docs)
collectionRef.get().then(snapshot => {
  snapshot.docs.forEach(doc => {
    // doc が ドキュメントリファレンスである
    console.log(doc.data().message);
  });
});

```

### コレクションをリアルタイム取得する
リアルタイムリスナーを用いることでリファレンスをリアルタイム同期できる。
当然、含まれるドキュメントもリアルタイム同期される。

get()の代わりにonSnapshot()を用いる。
onSnapshot()の引数にコールバック関数として続く処理を記述する。
ここで渡したコールバック関数は同期のたびに、
すなわちコレクションやドキュメントの内容が代わるたびに実行される。

下記はvueでdata()にmessages(配列)が定義されているとして、
その内容をfirestoreとリアルタイム同期する場合の例。

```hogehoge.js
// コレクションリファレンスの取得
const collectionRef = this.$fire.firestore.collection('messages'); 

// リアルタイムリスナの登録
// onSnapshotに渡されるコールバック関数は同期毎に実行される。
collectionRef.onSnapshot(snapshot => {
  // 同期毎に走るのでthis.messagesの中身は初期化
  this.messages = [];
  
  // snapshotの中身はコレクションスナップショット
  snapshot.docs.forEach(doc => {
    this.messages.push(doc.data().message);
  });
});

```

### コレクションにドキュメントを追加/更新/削除する
次のように行う。
messageプロパティのみを持つドキュメントからなるmessagesコレクションがあると想定する。

```hogehoge.js
// 保存.IDは自動採番される
const collectionRef = this.$fire.firestore.collection('messages');
collectionRef.add({
  message: '[新規メッセージ]'
}).then(res => {
  // 保存後の処理
}).catch(err => {
  // 失敗時の処理
});

// 更新.まずは更新対象とするドキュメントリファレンスを取得する
const docRef = collectionRef.doc(<ドキュメントID/ドキュメントパス(doc.idなど)>);
docRef.update({
  message: '[新規メッセージ]'
}).then(res => {
  // 保存後の処理
}).catch(err => {
  // 失敗時の処理
});

// 削除.基本的には更新と同じ手順。ドキュメントリファレンスを取得してからdelete()を呼びだす
const docRef = collectionRef.doc(<ドキュメントID/ドキュメントパス(doc.idなど)>);
docRef.delete.then(res => {
  // 削除後の処理
}).catch(err => {
  // 失敗時の処理
});
```


## 参考
[Nuxt firebase 公式解説サイト(デプロイまで)](https://firebase.nuxtjs.org/guide/getting-started)
[Nuxt firebase 公式解説サイト(firestore導入)](https://firebase.nuxtjs.org/service-options/firestore/)
[Nuxt firebase 公式解説サイト(認証について)](https://firebase.nuxtjs.org/service-options/auth/)
[Authenticationについて](https://zenn.dev/watson_sei/articles/f4db7312494525)