シンプルにVue(nuxt)+Firebaseで取得＆最終的にnuxtプラグイン化

vueもfirebaseも初心者が調べても色々難しいので、シンプルに理解できるようにします。
※firebaseの設定終了済みする。

~~※多分ミドルウェア化しないとログインの永続化が出来ないので、理解できたら追記します~~
2018/8/27 Middleware化はできなかったのですが、plugin化の時点でstore.stataに投げ込めたので追記

# 使うモノ・ファイル
ターミナル(VDCODE上のターミナルを使っています)
firebase
index.vue (index.vueですべて賄うパターンを参考)
plugins/firebase.js (プラグイン化を参考)
nuxt.config.js (this.$プラグイン名で使えるようにするを参考)

# 参考

[Firebase公式のドキュメント](https://firebase.google.com/docs/web/setup?hl=ja)のnode.js用を参考にします。

VanillaJSでは、firebase-app.jsなどをscriptタグで追加していましたが、vueなどのframeworkを利用するのときはfirebase SDKを利用します。

## 必須：Firebase SDKインストール
firebase SDKを利用するにはカレント作業ディレクトリにterminalでnpmを使ってインストールします。

```terminal:ターミナル
$　npm install firebase --save
```


## index.vueですべて賄うパターン
[Firebaseコンソール](https://console.firebase.google.com/)でプロジェクトの設定を取得してinitializeAppを上書きしてください。
(設定ファイルを作成する方法もある。そのうち書き換える）

```vue:index.vue
<template>
    <button @click="fbtest">FBテスト</button>
</template>
<script>
//FirebaseSDKを読み込む
var firebase = require("firebase");
//初期設定
firebase.initializeApp({
    apiKey: YOUR-,
    authDomain: YOUR-,
    databaseURL: YOUR-,
    projectId: YOUR-,
    storageBucket: YOUR-,
    messagingSenderId: YOUR-
});

export default {
  methods:{
//fbtestのボタンが押された時
    fbtest(){
//const refにあるデータを取得して
      const ref = YOUR_DATABASE;
      firebase.database().ref(ref).on('value', function(snapshot) {
          if (snapshot.val() !== null) {
//Consoleに表示
              console.log(snapshot.val());
          }
      });
    }
  }
}
</script>
```

上記でFBテストを押すとFirebase.databaseから情報を取得し、Console.logに表示します。

## プラグイン化
※ここからはnuxt前提です。
上記だと使いまわしが悪いのでプラグイン化します。
nuxtでは、プロジェクト上にpluginsフォルダがあります。
pluginフォルダにfirebase.jsを作成します。
そしてindex.vueから以下の部分を移動させます。

```vue:index.vue
<script>
//このコメントアウト部分をplugin化する　
//firebase appを全部使えるようにする
// var firebase = require("firebase");
//初期設定を追加
//firebase.initializeApp({
//    apiKey: YOUR-,
//    authDomain: YOUR-,
//    databaseURL: YOUR-,
//    projectId: YOUR-,
//    storageBucket: YOUR-,
//    messagingSenderId: YOUR-
//});

export default {
  // ：
}
</script>
```
↓ plugin/firebase.jsを作る

```js:firebase.js
//firebase appを全部使えるようにする
var firebase = require("firebase");
//初期設定を追加
firebase.initializeApp({
    apiKey: YOUR-,
    authDomain: YOUR-,
    databaseURL: YOUR-,
    projectId: YOUR-,
    storageBucket: YOUR-,
    messagingSenderId: YOUR-
});
//pluginが読み込まれたら　var firebase を　export
export default firebase;
```
↓ index.vueでfirebaseプラグインを読み込む

```vue:index.vue
<script>
//作成したプラグインを読み込む
import firebase from '~/plugins/firebase'

export default {
  // ：
}
</script>

```

これでfirebaseをプラグイン化できました。
でもこれだと他のページで使いづらいでので、更に汎用性を高めます。

## this.$プラグイン名で使えるようにする
マイページ毎にプラグインを読み込むのはかっこよくないので、サイト全体で使えるようにします。
nuxt.config.jsに作ったプラグインを追加します。
※configの設定を変更した場合は、アプリの再起動が必要

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

そして先に作成したfirebase.jsプラグインのexportをinjectできるようにする
(※ここまだ曖昧なので補足ほしい)

```js:firebase.js
//firebase appを全部使えるようにする
var firebase = require("firebase");
//初期設定を追加
firebase.initializeApp({
    apiKey: YOUR-,
    authDomain: YOUR-,
    databaseURL: YOUR-,
    projectId: YOUR-,
    storageBucket: YOUR-,
    messagingSenderId: YOUR-
});

//export default firebase;
export default ({ store }, inject) => {
    inject('firebase', firebase)
}
```

↓

```vue:index.vue
<script>

//↓ nuxt.config.jsで読み込むようにしたので不要
// import firebase from '~/plugins/firebase'

export default {
  methods:{
    fbtest(){
      var ref = YOUR-;
//firebase.database()をthis.$firebase.database()に変更
      this.$firebase.database().ref(ref).on('value', function(snapshot) {
          if (snapshot.val() !== null) {
              console.log(snapshot.val());
          }
      });
    }
  }
}
</script>
```

# index.vueのサンプル

```vue:index.vue
<template>
      <button @click="fbtest">FBテスト</button>
</template>

<script>
export default {
  methods:{
    fbtest(){
      var ref = '';
      this.$firebase.database().ref(ref).on('value', function(snapshot) {
          if (snapshot.val() !== null) {
              console.log(snapshot.val());
          }
      });
    }
  }
}
</script>
```
```js:plugins/firebase.js
var firebase = require("firebase");
firebase.initializeApp({
    apiKey: YOUR-,
    authDomain: YOUR-,
    databaseURL: YOUR-,
    projectId: YOUR-,
    storageBucket: YOUR-,
    messagingSenderId: YOUR-
});
export default ({ store }, inject) => {
    inject('firebase', firebase)
}
```
```js:nuxt.config.js
module.exports = {
  //:
  plugins: [
    '~/plugins/firebase'
  ],
// :
  build: {
    //:
    vendor: [
      'firebase'
    ]
  }
}
```

## plugin/firebase.jsでauthの永続化
2018/8/27 追加：
ベストプラクティスではないと思いますが、
**プラグインはページコンポーネント描写よりも先に発火**するので、プラグイン上で認証させ、store.state.userに追加します。

```js:plugins/firebase.js
const firebase = require('firebase/app');
var config = {
    apiKey: YOUR-,
    authDomain: YOUR-,
    databaseURL: YOUR-,
    projectId: YOUR-,
    storageBucket: YOUR-,
    messagingSenderId: YOUR-
};
firebase.initializeApp(config);

export default ({ store }, inject) => {
    //this.$forebaseで使えるように
    inject('firebase', firebase)


   //fireabase authでログイン済みの場合
    let p =  new Promise((resolve, reject) => {
        firebase.auth().onAuthStateChanged((user) => resolve(user || false))
    })
    //認証をストアアクションで
    return p.then(user=>store.dispatch('actionFirebaseUser', user));
}
```

## middlewearで認証の永続化
※9/22追加

```js:middleware/auth.js
const firebase = require('firebase/app');
require("firebase/auth")

export default function ({ store, route, redirect }) {
	return new Promise((resolve, reject) => {
		firebase.auth().onAuthStateChanged((user) => {
			if (user) {
				console.log(user);
				resolve(user);
			} else {
				location.href = '/';
			}
		});
	});
}

```

```vue:user.vue
<template>
</template>
<script>
export default {
    middleware: ['auth'],
// :
</script>
```