17
9

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Nuxt.js #2Advent Calendar 2018

Day 16

nuxt.js + firebase でPWA,SSRな借りパクを撲滅するアプリを作っている話

Last updated at Posted at 2018-12-16

この記事はNuxt.js #2 Advent Calendar 2018 16日目の記事です。

某webマーケティング会社でフロントエンドエンジニアとして働きながら、バンド活動もおこなっているtarooooooooooです。
バンド活動をしていると何かと支払いのタイミングが多く、バンドメンバー間での一時的な金銭などの貸し借りが多く発生してしまいます。
今まではLINEのグループ内にメモとして残していたのですが、どこまでが返却済みなのかを把握するのが難しかったためアプリを作ることを決意しました。

この記事ではアプリの概要についてとfirebaseの認証・ルーティング周りの話をします。

firestore周りの話はこちらに書きました。
firestoreのSecurity Ruleを設定して特定のuserのみが閲覧できる設計をする

アプリの概要

貸し借りを可視化するという意味をこめて「Cashica」というサービス名にしました。
まだまだ制作中でデザインやUIは改善予定です。(スマホでの利用を前提としているのでPCで見るとデザインの崩れがひどい。。)
機能としてはシンプルでユーザ間の貸し借りが登録、削除できるだけというものです。
友達登録にはQRコードの読みこみで対応しています。
下記にソースコードとsampleを置いていますのでご覧ください。

技術的にはnuxt.jsとfirebaseのfirestore, authentication, cloudfunctionを使っている構成になっています。

easypay-dd04a.firebaseapp.com_(iPhone 6_7_8).png

GitHub: https://github.com/taroodr/cashica
Demo: https://easypay-dd04a.firebaseapp.com

認証について

以下のように認証情報取得用のpluginを準備します。
async,awaitで呼び出せるようにfirebase.auth().onAuthStateChanged()メソッドを直接呼ぶのではなくpromiseのラッパーを作ると便利になります。

~/plugins/auth.js
import firebase from '~/plugins/firebase'

function auth() {
  return new Promise((resolve, reject) => {
    firebase.auth().onAuthStateChanged(user => {
      resolve(user || false)
    })
  })
}
export default auth

このpluginをコンポーネントがmountされた際に下記のように使うことで、認証情報がvuexに格納されていない場合に認証情報を取得できます。

~/pages/signin.vue
import auth from '~/plugins/auth'

export default {
  async mounted() {
    let user
    if (!this.user) user = await auth()
    await Promise.all([
      this.user
        ? Promise.resolve()
        : this.$store.dispatch('SET_CREDENTIAL', { user: user || null })
    ])
  }

認証情報の取得はsignin.vueのみで行なっている設計になっているのですが、これは認証状態によってリダイレクトを行うmiddlewareによってかならず/signinにリダイレクトされる仕様になっているためです。

~/middleware/authentiated.vue
export default function({ store, route, redirect }) {
  if (!store.getters.isAuthenticated && route.name !== 'signin') {
    redirect('/signin')
  }
  if (store.getters.isAuthenticated && route.name === 'signin') {
    redirect('/')
  }
}

middlewareはnuxt.config.jsに下記のように記載することでルートの変更を検知するたびにmiddlewareの内容を実行してくれます。

nuxt.config.js
export default {
  router: {
    middleware: 'authenticated'
  },
}

再読み込みしたタイミングで一度/signinにリダイレクトされてしまうので、認証情報の取得が終わるまでloading用のコンポーネントを表示をおこなっています。

~/pages/signin.vue
export default {
  async mounted() {
    let user
    if (!this.user) user = await auth()
    await Promise.all([
      this.user
        ? Promise.resolve()
        : this.$store.dispatch('SET_CREDENTIAL', { user: user || null })
    ])
    if (user) {
      this.$router.push('/')
    } else {
      this.loadComplete()
    }
  },

疑問

上記の実装だと、必ず/signinに一度リダイレクトされてしまうのが気持ち悪いのですが何か解決方法はないのでしょうか?
詳しい方いらっしゃいましたら教えてください:clap::clap:

やり残したこと

1週間ほど前から作業を行なっていたのですが、想像以上に進捗がよろしくなく必須だと考えていたpush通知機能をつけることができませんでした。。。
firebase cloud messagingを使うと楽に実装できそうですので、完成し次第また記事を書こうと思います。

雑感

参考文献

制作にあたり下記記事には大変お世話になりました。
https://qiita.com/potato4d/items/cfddeb8732fec63cb29c
https://blog.shimar.me/2018/03/31/nuxt-firebase-authentication.html

17
9
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
17
9

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?