ペイの技術MEMO

文系大学生の技術メモ

Nuxt.js + firebaseで「積ん読防止」アプリを作ってみた

この記事は「JX通信社Advent Calendar 2019」の14日目の記事です。

はじめに

こんにちは。JX通信社でエンジニアインターンシップをしているペイと申します。

1ヶ月ほど前からKI-develop1積ん読を防止できるアプリBookMotionを開発しています。

今回はBookMotionでWebフロントとfirebaseを担当したので作っていて良かったこと(主にWebフロント)など紹介できればと思います。

開発環境や具体的なコードの記述はないので知らなかったことが知れると思ってお読みください。

作ったもの

ランディングページ / BookMotion WEB(β版)

BookMotionは積ん読を防止する為に、読みたい本を簡単に登録

読書のモチベーションを維持することできるようになっているアプリです。

特にエンジニアの方は,技術書を沢山積んでいるのではないでしょうか?

BookMotionはweb版でβ版として一般公開, iOS, Androidは準備中です。


WEB版の様子

積み本のリストを表示している画面。

読書開始日、読書終了予定日を設定することができます。(モバイル版ではpush通知を予定) スクリーンショット 2019-12-09 21.23.10.png

積みたい本気になる本をデータベースから検索している画面 スクリーンショット 2019-12-09 21.24.27.png

スマホ表示

スクリーンショット 2019-12-09 21.42.38.png

スクリーンショット 2019-12-09 21.44.12.png

使った技術

フロントエンド

インフラ

実装していて良かったこと

Nuxt(SPA)のここが良い

前提: SPAモードで実装した場合の話をしています。

1. middlewareが便利

Vueを触っている人なら一度は見たことがある、ライフサイクルの図があると思います。

vueではインスタンスが生成されてからDOMが構築されるまでに順序があります。

例えば頻繁に使用される、createdインスタンスが生成された後に実行される為、コンポーネントが呼ばれて最初に走らせたい処理などを呼ぶことができます。

しかし、インスタンスが生成されてから、API等でサーバーにリクエストする時、ログインの情報からドメインとなる情報まで複数持ってくるのは難しいです。

キャッシュさせたり、ローカルストレージに保存する方法などもあると思いますが、ブラウザ上でデータを持っておくのはあまり好ましくなかったりします。

そこでコンポーネントが呼ばれる(インスタンスが生成される)前にミドルウェアを挟んで、そこでログインの状態などがわかると便利じゃないですか?()

Nuxt.jsではmiddleware が使えます。実装の方法によっては本当に便利です。

実装

middlewareの処理を書く

middlewareディレクトリの配下に任意のファイルを作成 今回はauthenticated.jsというファイルで作成する

export default function({ route, redirect, store }) {
  /**
    任意の処理
    route.nameでpathを取得できる
    store.state.hoge のようにvuexにアクセス可能
    redirect('/login')でリダイレクトしてくれる
  */
}
nuxt.config.jsにmiddlewareの名前追加する

middleware/authenticated.jsというファイル名の場合は、以下のように記述します。

authenticatedはミドルウェアのファイル名によって変わるので適宜変更してください。

export default {
  mode: 'spa',
  // ~省略~
  router: {
    middleware: ['authenticated'] 
  }
}

firebaseでのログインを実装する場合は以下の記述で現在ログインしているユーザーを取得することができるので実装の方法によってはミドルウェアに挟めてログインの状態を各ページが呼ばれる前に確認することができます。

import { auth } from '~/plugins/firebase'
auth.onAuthStateChanged((user) => {})

2. pluginを使ってモジュールを呼び出せる

NuxtのpluginはNuxt.jsで作っているインスタンスが生成される前に呼ばれるので外部モジュールなどを呼ぶ時に便利です。

上記で紹介したmiddlewareは各ページが呼ばれる前に実行したい関数がある場合などが適していますが、

pluginはルートのアプリケーションがインスタンス化される前に実行されるのでページ転移する度に関数を実行したいという時には適していません。

例えばfirebaseのイニシャライズ処理をしたい時などにおすすめです。

import * as firebase from 'firebase/app'
import config from '~/firebase.config'

if (!firebase.apps.length) {
  firebase.initializeApp(config)
}

export const auth = firebase.auth()

また、全てのVueコンポーネントで特定の関数を使用することができます。 下記はインスタンスへ注入する場合です。

import Vue from 'vue'

Vue.prototype.$hoge = foo => console.log(foo)
export default {
  mounted () {
    this.$hoge('hello')
  }
}

またNuxtにはInjectという機能があり、共通の関数を定義することができます。 Injectを使ってDIをしている方の記事も上がっているので興味がある方は調べてみてください。

vue-property-decoratorを使ってコードを見やすく

VueをTypeScriptで書く為のライブラリです。

jsで書くVueでは、Propsなどを除いて型安全ではないで今回使いました。

また、素のVueは,カンマが多く登場するので、コードの見通してもよくありません。

以下jsで書いた場合

export default {
  data: () => ({
    hoge: false,
  }),

  computed: {
    foo: {
      get() {
        return ['menu-icon', this.hoge ? 'rotate-icon' : '']
      }
    },
  },
  created() {
    this.hoge2()
  },
  methods: {
    bar() {
      this.$refs.foo2
    }
  }
}

以下はvue-property-decoratorを使って上記のコードをリファクタしたコードになります。

<script lang="ts">
import { Component, Prop, Vue } from 'vue-property-decorator'

@Component
export default class Index extends Vue {
  hoge: boolean = false
  get foo(): Array<string> {
    return ['menu-icon', this.hoge ? 'rotate-icon' : '']
  }
  created() {
    this.hoge2()
  }
  bar(): void {
    this.$refs.foo2
  }
}

無駄な,がなく、スッキリしたコードになりました。また、戻り値を書くことで型安全になりました。

特にAPIを叩いてデータを流し込む際は型がないと、正しい値を入っていると保証できないので、型をしっかり定義してあげることは重要です...

詳しい書き方はvue-property-decoratorで調べると記事が結構出てくるので調べてみてください。

Firebase UIで認証の見た目を実装

今回はログイン認証をFirebase Authenticationを使って実装しました。

Vueで実装する場合はとても簡単でFirebase UIのプラグインを読み込んで,インスタンスを生成したらtemplate内のタグに埋め込むだけで使用できます。

公式のページを読むだけで実装できたので、機能の開発に集中したい時や、ログインの実装を任せたい時はおすすめです。

現状の課題

Atomic Designの粒度があっているのか分からない。

現状Atomic Designもどきで実装しています。

Atomic Designは機能によって粒度を分けるのですが、moleculesとorganismsの境目が本当に正しいのかどうか、

再利用性の低いコンポーネントをわざわざmoleculesに分ける必要があるのか、

など気になる点が多くあり、今後の課題です。

今後について

webフロントでは実装が増えるごとに手動でのデザインの確認やロジックの確認をすることに限界を感じているのでそろそろテスト導入していかないといけないなーって感じています。

また、コンポーネントが増える毎に自分が実装したAtomic Designに幻滅するのでリファクタを重ねていかないとなーって感じです。

さいごに

firebaseを使うことで、各自メインの機能を作ることに集中できました。

Firestoreのデータモデルに最初は苦戦しましたが使ってみるとRDBより楽なのでは?と感じたりもするの色々触ってみるのも大事だなと感じました。

BookMotionはweb版でβ版として一般公開, iOS, Androidは準備中なので、積ん読しちゃっている人は是非使ってみてください!!

参考文献

https://blog.shimar.me/2018/03/31/nuxt-firebase-authentication.html

https://tech.cydas.com/entry/nuxt-inject

https://qiita.com/ryo2132/items/4d43209ea89ad1297426


  1. 自分を含め大学生3人でwebサービスなどを開発しているチーム名twitter.comtwitter.comtwitter.com