LIFF でゲームアプリを作るまで

# はじめに
LINE Frontend Framework(LIFF) でゲームアプリを作りました。
作る過程や困ったことを紹介し、参考にしていただければと思います。

## LIFF とは
LIFF アプリとは LINE 上で開く web アプリのことです。
LINE とつなげているので、LINE のアカウント名やアカウント画像を簡単に取得することができます。

## 今回作ったゲーム
インサイダーゲームというゲームを作りました。[Amazon](https://www.amazon.co.jp/Oink-Games-OIN09023-Insider/dp/B01M5FYKL4)
ボードゲームバーで体験してみて面白かったので、アプリにすることにしました。
この記事を読む上では、人狼のようなものだと思っていただければいいです。

## 使っている技術

#### [Nuxt.js](https://ja.nuxtjs.org/)
業務でも使っていることもあり、web アプリは Nuxt.js で作りました。
ちなみに、 UI フレームワークは [Vuetify](https://vuetifyjs.com/) を使いました。

#### [Socket.IO](https://socket.io/)
別の端末とのやりとりは、 Socket.IO を使っています。
Firestore を使えば楽なのですが、 WebSocket をちゃんと学びたかったこともあり、こちらを採用しました。

#### [Heroku](https://devcenter.heroku.com/)
バズったらプラットフォームは変えるつもりですが、まずは無料で使えるので Heroku でアプリを公開しています。
公開には webサーバーと nodeサーバーが必要で、両方とも Heroku で公開しています。

#### [LIFF](https://developers.line.biz/ja/docs/liff/)
上記 web アプリに LIFF でアクセスするようにしています。
LINE からは名前とIDの取得をしています。
そして一緒に遊ぶ人にリンクを配布するために[シェアターゲットピッカー](https://developers.line.biz/ja/reference/liff/#share-target-picker)を使っています。

## 実装のポイント

各種技術の使い方は散々記事にされているので、ポイントだけを記述します。

#### Nuxt.js での Web アプリ作成
まずは LINE 連携をしない状態で Web アプリを作るのがいいと思います。LINE から取得したい情報はひとまず mock化などして、Web ブラウザで動かすイメージです。
できている状態のものに LIFF を機能として乗せる方が LIFF URL の修正などが発生しないので後戻りが少なくて済むと思います。

この状態のアプリを Heroku にデプロイします。

#### Socket.IO との連携
[こちら](https://qiita.com/at-946/items/590e618b041182b151ed) の記事を参考にし、docker で Webアプリと Nodeサーバーを立ち上げることができました。
この記事通りにやると `docker-compose` で Webサーバーと Nodeサーバーが一度に立ち上がります。
しかし、 Heroku にデプロイするとポートを分けるあたりでうまくいきませんでした。
Webアプリと Nodeサーバーの二つに分けてデプロイすれば問題なく動きそうなので、レポジトリ単位で分けることにしました。

#### LIFF 導入
LIFF の導入にあたり、まずは [LINE Developers](https://developers.line.biz/ja/) のサイトで登録をする必要があります。
同じチャネル内に開発用と本番用で LIFF URL を発行します。
開発用には後述する localhost を公開した URL を、本番用には Heroku にデプロイした Web アプリの URLをエンドポイントURLとして指定します。

Nuxt.js に `@line/liff` をインストールします。
LIFF のドキュメントを見て実装したのですが、後述する困ったポイントが多くて結構てこずりました。
PC のブラウザ(外部ブラウザ)と LINE内ブラウザ(LIFF ブラウザ)で挙動が違うので、デバッグの手間もかかります。
挙動の違いから `liff.isInClient` や `liff.isLoggedIn` で処理を分ける必要があり、結構骨が折れました。
LIFF アプリを作る中で同じように苦悩を抱えた場合は、後述の「困ったポイント」が参考になれば幸いです。

ログインができて ID が取得できれば、シェアターゲットピッカーなどは何もつまづかず動かせました。

## 困ったポイント

### localhost を LIFF 起動時の URL にできない
デフォルトで nuxt を起動すると `http://localhost:3000` の URL になりますが、LIFF 起動時の URL は https にする必要があります。
こちらは nuxt で https を使えるようにすることで対処できました。[参考](https://qiita.com/nobita_x009/items/0ce13d7ba08a287fbf94)

### スマホでの動作を確認する方法
LIFF の[ドキュメント](https://developers.line.biz/ja/docs/liff/developing-liff-apps/)をみてもらうとわかるのですが、外部ブラウザと LIFFブラウザで起動した時の挙動が結構違います。
なので開発中に LIFF ブラウザでの挙動を見るために localhost を公開する必要がありました。
そこで、 [ngrok](https://ngrok.com/) を使って localhost を公開し、それを LIFF のエンドポイントURLに指定して開発しました。

### LINE のアカウントベースでの開発になるので、対戦時の挙動を試せない
個人開発なので、使える LINE のアカウントが一つしかないです。
そのため、対戦時の挙動を試すことができずに困りました。
これは URL に ID を受け付けて、それを LINE ID として動作させることでデバッグできるようにしました。

### `liff.init` をしてもリダイレクトしてくれない
LIFF の[ドキュメント](https://developers.line.biz/ja/docs/liff/opening-liff-app/#redirect-flow)によると `liff.init` をするとリダイレクトしてくれるはずなのですが、 LIFF ブラウザで確認したところ、リダイレクトされませんでした。

``` js
async mounted() {
  await liff.init();
}
```

こちらは、`setTimeout` で囲うことでリダイレクトされるようになりました。(なんでかは分かってないので詳しい人いたら教えてほしいです)

``` js
async mounted() {
  await setTimeout(() => {
    liff.init();
  }, 0);
}
```

### `liff.init` をした後の2次リダイレクト先で LINE の情報が取得できない
LIFF の[ドキュメント](https://developers.line.biz/ja/docs/liff/opening-liff-app/#redirect-flow)によると `liff.init` をした後のリダイレクト先(2次リダイレクト先)で LIFF アプリを表示するように指示されていましたが、 LIFF ブラウザでみた時に、2次リダイレクト先で LINE の情報が取得できませんでした。
2次リダイレクト先でもう一度 `liff.init` を実行することでうまくいきました。
(ドキュメントには「1次リダイレクト先URL以外のタイミングでliff.init()メソッドを実行すると、INIT_FAILEDが返され、LIFFアプリを開けません。」とありましたが、2次リダイレクト先で `liff.init` をしても問題ありませんでした。)

### [nuxt/axios](https://axios.nuxtjs.org/) を使うと Safari で `Network Error` が起きる
自分は iPhone を使って LIFF の動きを確かめていたのですが、外部に繋ぐために nuxt/axios を使ってアクセスしようとしたら `Network Error` が発生しました。
LIFF ならではの問題だと思ってデバッグに非常に時間がかかったのですが、PC版の LIFF の問題ではなく Safari の問題でした。(iPhone の LIFF ブラウザは Safari ベースらしい)
代わりに [axios](https://github.com/axios/axios) を使えばうまく行きました。 


# 最後に
LIFF を使う上で忘れがちな[ガイドライン](https://developers.line.biz/ja/docs/liff/overview/#development-guidelines)を確認しておくといいです。
特に「ユーザーの同意なく、cookie、localStorage、またはsessionStorageを使ってユーザーをトラックしたり、LINEのユーザー情報と外部セッション情報を結びつけたりしないでください。」はやりがちかなぁと思うので気をつけてくださいね。

最後に、作ったゲームは[こちら](https://liff.line.me/1655536378-keMgeWod/main)です。ゲーム自体も楽しいのでぜひ4人以上集めてやってみてください。
なお、 Heroku でデプロイしているので、起動までに 30秒ぐらいかかるかもしれません。