Firebase+Vue.js(composition-api with typescript)でオセロを作った感想

# はじめに

次のエントリー用のメモです。
読み飛ばして、質問があればできる限りでエントリーするつもりです。

https://github.com/iwamoto-takaaki/reversi

題の通り作りました。
スマホでやってもリアルタイムに反映されるので面白い。

ひっくり返すのを自分でしなきゃだったり、ルール無用で置けたりだけど・・・

# 見どころ
 
- 組み合わせとしてはqiitaにはたくさんあるエントリー
- composion-api + typescript　は少し珍しい
- pugやsassが見ずらいという人、ごめん
- firebase+vueで組む場合の戦略など
- 細かい部分はあとで別記事書きますのでリクエストあれば優先します

# なぜFirebaseとvueは相性が良いのか

サーバーが要らず、サーバとの通信も気にせずアプリケーションに集中できる。実のところReactとか競合する他のフレームワーク使って無いのでVueに限った話でも無いかも。

## データバインディング!!

正直、おすすめはこの一点にあり、あとはおまけだと言いたいくらい。

FirebaseにはSnapshotという機能があり、リアルタイムリスナーをクライアントと結びクエリの結果に変更があった際に通知する機能がある。Vueにはデータ変更があった場合、変更を即座に画面に反映させる。これを組み合わせると、一度クエリを投げたらリアルタイムに更新。

1. Firebaseはリアルタイムリスナーによりクライアントに変更内容を通知する
1. クライアントはそれをVueのstateに適用する(コーディングする部分)
1. Vueはstateの変更を検知して、画面の再描写(差分のみ)をおこなう。

※リアルタイムリスナーってなにか私はよく判っていません。（websocketよりブラウザの縛りが少なく、ちょっとだけ遅いらしい。）

```
Firebase(リアルタイムリスナー) -> クライアント（コールバック）　-> reactive(再描写)
```

つまり、開発時にクライアントとサーバのやり取りはほとんど意識する必要がなく、データの変換を定義するだけ。

## RailsやLaravelよりVueが良い理由

もちろん、Firebaseとの相性の話ですよ。
Firebaseのみで完結し、サーバがいらないから。コードに集中できる。

たとえばRailsやLaravelと組み合わせる場合、RailsやLaravelのサーバを用意しなきゃならない。ところがVue.jsでは、SPAなので1つの固定ページでwebアプリケーションが簡潔する。これをFirebaseのHostingというサービスで提供すると、Firebaseのみで済む。

僕はバックエンドエンジニアなんだけどインフラは得意じゃない。フロントエンドの人や初学者はもっとそうではないかと思う。セキュリティー面で考慮すべきことも格段に減るのも優れた点だと思う。

## 安い

従量課金制なんだけど、サーバレスなのでCPU時間とかデータ量とか通信量なので初期費用が0なのがありがたい。
https://firebase.google.com/pricing

サーバーが必要だとどうしても最低額が必要になる。復数のサービスをkubernetesで走らせてるって言う人は関係ないだろうけど。サーバがなく利用量と金額が初期から線形に一致するというのはかなりのメリットだと思うし、今回の用に限定公開を行う場合においては課金が起こることはまずないとおもっていい。

小規模な社内システムなんかもFirebaseで組むとインフラの計画や費用の計画などする必要が無いのでよいと思う。サービスが成長し、めでたく割高になったら、利用しているサービスを一個ずつ他に移動すれば良い。

## ものすごく軽い

Single Page Application（SPA)の利点ですね。

# 利用した技術など

## Firebaseで使ったもの

### Firestore

NoSQLデータベース。
firebaseには、もう一つRealtime Databaseがあるけど今ひとつ違いが判らないので、とりあえずFirestoreを使っている。

ちょっとハマったのが、階層型のデータベース構造を持っていて、復数のドキュメントを集約したものがコレクションで、ドキュメントはコレクションを持てるという構造。これによって、データベースの構造は、`root/collection1/document1/collection2/`みたいなパスでアクセスする。

あと、インデックスにも癖があり、ハマった。ここらへん詳しく書きたいけど調べが足りない。

結構独特な使い方だけど、ブラウザからDBを直接操作できるようになっていて、(かつセキュリティも満たせる)面白いので別エントリで書きたい。

バックアップも試していない。少なくとも今はJSONでExport&Importで済む量だから。

### Firebase Hosting

https://firebase.google.com/docs/hosting
静的ファイルのホスティング。

ここにVueのビルド結果のファイルを置く。動的コンテンツだったらCloud Functionsで構築する必要がある。Functions上でどんなフレームワークが有効かは興味があるが今は知らない。

### Firebase Authorication

https://firebase.google.com/docs/auth
Email承認やGoogle Account以外にTwittergithubログインを可能にできる。

ログインの状態はデータベースと同様に ログインしているユーザーのスナップショットを取得できる。

### Functionsは使っていない

使わないでアプリが作れるのが良いところなんだけど、実際サニタイズなどを真面目にやろうとすると必要。
呼び出し方は、HTTPリクエストもあるんだけど、バッチやデータ登録を起点にできるらしい。
つまり、フロントエンドからお気楽にデータ登録をしているように見えて、バックエンドではFunctionsがバッチリとサニタイズして、リジェクトしたりエラー返したり、履歴をバックエンドのDBに送ったりとかできる。

是非ともマスターしていきたい。

## Vue.jsで使ったもの

## Vue Router

ゲーム画面を共有するには一意なURLを定義する必要があるので使っている。

## Vuexは使っていない

Vuexはページをまたいだ状態の管理ができるのが便利。またサーバとのデータアクセスが、構造化できる。型安全でオブジェクト指向にしたいので、vuex-module-decoratorsを入れたが思ったような挙動をしてくれなかった。

使い方が悪かったのは自分の能力不足であるけど、Vueを使うのしReactiveの動作についての理解がどうしても必要でその当たりが、見え辛いツールだと思う。また、Vuexで状態を持つのではなくFirestoreのsnapshotがあれば大きく不自由は感じないというのもある。

その点、composition-apiはわかりやすかった。（とはいえ使いこなすには時間がかかった。）この点もそのうちエントリーしたい。

### composition-api

今回使ったVueは２．６何だけど、Vue３で導入されるcomposition-apiはアドオンでインストールできる。setupメソッドの中でReactiveとComputedを定義して、setupメソッドの実行スコープで定義されたReactiveとComputedのみが再描写の対象となる。
(see: [先取りVue 3.x !! Composition API を試してみる](https://qiita.com/ryo2132/items/f055679e9974dbc3f977))

これまでのVueは、Vueの中で定義されたメソッドが対象だったために外部のモジュールで定義したモジュールは値を変更しても再描写がおこらない。これに対してWatchなどで対応する方法もあるんだけどまどろっこしいし、動作も重いらしい。

composition-apiだとsetup中に呼び出したReactiveやComputedも対象になるので、外部モジュールはコンストラクタで定義を行うと再描写の対象になる。ある種独特の組み方になるので非常にわかり辛かったが、やり方が分かるとTypescriptの型安全を利用して組むことができるので非常にありがたい。

モジュール化はできたものの、モジュール間でオブジェクト指向らしい相互作用を実現できていない。今回の場合は、Firebaseのスナップショット関心事の通知が行われるので特に問題はないが・・・

### Nuxt.jsは使わない

Firebaseでは、Serve Side Rendering(SSR)だとHostingが使えなくなるのでしない。Single Page Applicationをする機能もあるとも訊いているけどよく知らない。正直、メリットがよく判っていない。

## その他の技術

### [pug](https://pugjs.org/api/getting-started.html)

コンパイル時にHTMLに展開されるテンプレートエンジン。または、AlterHTMLかもしれない。
閉じタグどころか、タグのカッコ`<>`を書かなくていいので楽。行数が減ってコードが読みやすい。基本的は省略記法なので、Vueはタグとしてモジュールを指定するのでpugとの相性は良い。(余談だけど、Wordpressのテーマをpugで書こうとしたけどPHPのコードの中はHTMLのままになってしまうので相性が悪かった。)

また、記法がセレクタと同じなのでsass書くときにpugをコピペして要らんとこ削って書き始められるのすごく良い。

### [sass](https://sass-lang.com/guide)

中カッコ`{}`省略して良い程度の使い方しかしていないけど、使わいない理由が無い。

pugもそうだけどインデントが意味を持つ言語ってそれほど好きじゃない。でも、ネストが深いと閉じカッコがどんどん邪魔になる。行数が多くなるか、まとめると今度は個数の調整が面倒になる。こういうものにはカッコが無いほうがやりやすいと感じてる。

VueのStyleの設定をscopedで書くカラーパレットなどの変数を毎回インポートしなきゃいけないのが面倒。というか、毎回展開されるとロードに負荷が掛かりそうで嫌だ。

# まとめ

Vueはマジック（どのような原理で動いているかわからない）が良い点でもあり悪い点でもある。ちょいとカスタマイズしようとすると途端に引っかかる。基本的な動作原理を理解していれば問題ないけど、その点で苦労した。composition-apiはその点がわかりやすくなってくれてありがたい。

ソースコード的にはまだまた簡単にできる点があると思うしそもそも、粒立ちが揃っていないところもあるのでぼちぼち修正してベストプラクティスを作り上げたい。

Firebaseは、本当に気軽に開始できてサービスの成長に合わせて機能追加できると考えている。また、サーバレスってマイクロサービスアーキテクチャの最終形とも言えるので大規模になった際に移行もそれほど難しくないと思える。