LIFFアプリ開発徹底入門

## はじめに
業務でLIFFについて扱っているので、自身の学びのために一から簡易的なアプリを作って、その全体像を把握してみます。
LIFFアプリはReactとTypeScriptで作成します。

### 前提
本記事は以下の3つを前提として進めていきます
* Node.jsの導入が終わっていること
* LINE Buisinessアカウントのプロバイダーが作成済であること
* Renderのアカウントを作成済であること

LINEの設定、およびRenderアカウントの作成については以下の記事で触れていますので参考にしてみてください。
* [Node.jsとMessagingAPIでLINEの応答ボットを作る - LINE関連の設定](https://qiita.com/course_k/items/85bf9cfab971cb5b97ee#line%E9%96%A2%E9%80%A3%E3%81%AE%E8%A8%AD%E5%AE%9A)
* [Node.jsとMessagingAPIでLINEの応答ボットを作る - アカウントを作成する](https://qiita.com/course_k/items/85bf9cfab971cb5b97ee#%E3%82%A2%E3%82%AB%E3%82%A6%E3%83%B3%E3%83%88%E3%82%92%E4%BD%9C%E6%88%90%E3%81%99%E3%82%8B)

また上記以外の付加情報として、私の環境は
OSがMac Ventura 13.6.7
Node.jsのバージョンはv20.10.0
使用している開発ツールがVS Code
となっています。

## LIFFとは
LIFFとはLINE Front-end Frameworkの略で、LINEが提供するWebアプリのプラットフォームです。
LIFFを使うことでLINEの情報を使用したアプリケーションを作成することができます。

### 何ができるのか
何ができるかを確認するための簡易アプリをLINEが用意してくれています。
[LINEプレイグラウンド](https://liff-playground.netlify.app/)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/251137/e4913e7a-7416-adee-2e7f-56189bf6e551.png)

ざっとページを確認すると分かりますが、LINEログインや、OSの情報の取得、LINEプロフィールの取得など、様々な機能が用意されています。

こちらの調査によれば、スマホ・携帯利用者の8割がLINEを利用しているらしいので、LIFFを使うことでLINEと連携した便利なアプリケーションを作成することができそうです。
https://www.moba-ken.jp/project/service/20240422.html

習うより慣れよ、なので実際にLIFFアプリの開発を一から行ってみましょう。

## LIFFで簡単なアプリを作る
### 環境構築
#### viteの導入
`npm create vite`でReactのプロジェクトを生成しましょう。
プロジェクト名、使用するフレームワーク、JavaScriptかTypeScriptかを選択します。
今回は以下のような設定とします。
<img width='70%' src='https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/251137/ab156cc7-671b-d670-a462-4ea6d7318964.png'>

生成したプロジェクトのディレクトリへ移動し、依存関係のインストールを行います。
<img width='70%' src='https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/251137/a0e0579c-27f9-689d-6422-7ccf2c69075e.png'>

`npm run dev`でアプリを立ち上げます。
<img width='70%' src='https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/251137/baf8fdca-8d4c-550e-fc23-104784e7338f.png'>
`Local`のアドレスへアクセスし、以下のような画面が表示されれば成功です。

:::note warn
通常、viteのポート番号は5173ですが、私は別で使っていたので5174となっています。
:::
<img width='70%' src='https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/251137/72f06bc8-6697-9d40-0097-b3a0995678d8.png'>

#### LIFF SDKの導入
立ち上げたアプリを一旦終了し、以下のコマンドでLIFF SDKをインストールします。
`npm install @line/liff`
<img width='70%' src='https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/251137/4792edd7-579e-461e-6899-f9a356cecf91.png'>

### アプリの作成
#### ファイル・フォルダの整理
今回はユーザー名を取得して、「こんにちは、〇〇さん」と出力するだけのお手軽アプリを作ります。

まず、元から用意されているファイルやフォルダのうち、不要なものをは削除して以下の通りにします。
<img width='70%' src='https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/251137/fdd1d0a8-166c-cab1-5ee8-ac3d841c3277.png'>

そして2つのファイルを編集します。

#### index.htmlの編集
こちらはほぼ初期値のままですが、以下のようにしておきます。
```html:index.html
<!DOCTYPE html>
<html lang="jp">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>LIFF DEMO</title>
  </head>
  <body>
    <div id="root"></div>
    <script type="module" src="/src/main.tsx"></script>
  </body>
</html>
```
こちらは今回のアプリの動きに大きく寄与しないので特に解説しません。

#### App.tsxの編集
つぎに、`App.tsx`です。
```typescript:App.tsx
import liff from "@line/liff";
import { useEffect, useState } from "react";

function App() {
  const [userName, setUserName] = useState("名無し");
  const [isLoggedIn, setIsLoggedIn] = useState(false);
  useEffect(() => {
    liff
      .init({
        liffId: import.meta.env.VITE_LIFF_ID,
        withLoginOnExternalBrowser: true,
      })
      .then(() => {
        console.log("init");
        liff
          .getProfile()
          .then((profile) => {
            console.log("get profile");
            setIsLoggedIn(liff.isLoggedIn());
            setUserName(profile.displayName);
          })
          .catch(() => {
            console.log("get profile failed");
          });
      })
      .catch(() => {
        console.log("init failed");
      });
  }, []);

  return <h1>{isLoggedIn ? `こんにちは、${userName}さん` : "Loading..."}</h1>;
}

export default App;
```

一見複雑なように見えますが、抑えておくべきポイントは3つです。
##### liff.initの使用
LIFFアプリを使う上で、これは必ず必要になります。
この初期化を行うことで、ほかのliffのメソッドを使用可能になります。

initメソッドにはオブジェクトの形式で設定を渡すことができ、`liffid`のみが必須になります。
ここでは`liffid`には環境変数から取得した値を設定するようにします。
この値はLIFFアプリを登録したあとでないと取得できないため、一旦このようにしておきます。

また、LINE以外のブラウザから開いたときにLINEログインを強制できるように`withLoginOnExternalBrowser`オプションを`true`で設定しておきましょう。

##### 非同期処理の使用
`liff.init`は`Promiseオブジェクト`を戻り値として返却します。
これは非同期処理に関連するオブジェクトで、LIFF独自のものではなく、JavaScriptの仕様です。
Promiseについての詳細な解説はここではしませんが、成功したときの処理を`then`に、失敗したときの処理を`catch`に書くものと思ってください。

`then`、`catch`の引数にはそれぞれコールバック関数を渡す必要があるため、それぞれアロー関数で処理を定義しています。

##### liff.getProfileの使用
`liff.init`の成功した場合の処理`then`の中で、`liff.getProfile`を使っています。
これは、LINEでログインしてきたユーザーのプロフィール情報を取得できます。
`liff.getProfile`も`Promiseオブジェクト`を戻り値として返却します。

`then`に設定するコールバック関数は、引数としてプロフィール情報のオブジェクトを受け取ります。
そのオブジェクトから今回は`displayName`（表示名）を取得しています。

そのほかログイン状態を取得する`liff.isLoggdedIn`も使用していますが、これは見たままになりますので特に解説はしません。

これで、ログインしてきたユーザー名を画面に表示させるためのアプリが完成しました。

次からはアプリのデプロイ作業を行います。

## Renderへのデプロイ
### GitHubリポジトリの作成
RenderではGigHubリポジトリをもとにアプリをデプロイすることができるので、今回作成したプロジェクトをGitHubにあげます。
冗長になるのでここの手順は割愛します。

### デプロイ
Renderのマイページを移動し、「New」から「Static Site」を選択します。
<img width='70%' src='https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/251137/24f3bb95-7292-cc3e-166b-26f48e729331.png'>

先ほど作成したリポジトリを選択します。
<img width='70%' src='https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/251137/e6dc8cd9-fcf5-90e6-da56-a06df3de3cc3.png'>

設定情報の入力になりますが、基本デフォルトのままでよいです。
1つだけ修正が必要で、「Publish directory」に「dist」を入力してください。
※画像では空になっていますが、必須項目なので入力するようにしてください。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/251137/1087a5cc-4e98-477c-135c-d37e36c7ff17.png)

少し待つと、デプロイが完了します。
表示されているURLは後ほどLIFFアプリの設定で使うのでコピーしておきます。
<img width='70%' src='https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/251137/6c94773a-a5b5-6431-2b1e-6ca7b9bc632e.png'>

なお、今このURLにアクセスしてもうまく動きません。
LINEログインが発生しないので、「Loading...」のままになります。
<img width='70%' src='https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/251137/d9b38f17-851a-8d10-d301-8336adf479a3.png'>

コンソールにも初期化失敗のログが出力されています。
<img width='70%' src='https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/251137/47454f63-8780-132d-005c-9565bf43914e.png'>

次はRenderにデプロイしたアプリをLIFFアプリとして登録します。

## LIFFアプリの登録
チャネルを新規作成します。
<img width='70%' src='https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/251137/fa2a5f96-dda6-57d2-6f26-bce9d8b2f726.png'>

LINEログインを選択します。
<img width='70%' src='https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/251137/aaf22d66-dfde-36c8-1ff9-38aa6a7304ee.png'>

それぞれ必要事項を入力してください。
<img width='70%' src='https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/251137/9546bd12-2d53-599c-5b18-ea5c60dc6d9f.png'>

以下のようにチャネルが作成されます。
<img width='70%' src='https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/251137/f2440648-4060-cc4a-3472-04c386de822f.png'>

作成したチャネルの「LIFF」タブを選択します。
ページ下部の「追加」を押下します。
<img width='70%' src='https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/251137/91669ca2-0699-2bd8-1772-7ea51b6ef135.png'>

以下の通り、必要事項を入力してください。
「エンドポイントURL」は先ほどコピーしておいた、デプロイしたアプリのURLを設定します。
<img width='70%' src='https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/251137/9e10f86c-4544-3118-5f6a-eafa961e08e7.png'>

LIFFアプリの作成ができました。
「LIFF ID」をメモしておきます。
「LIFF URL」も後で使うのでメモしておきましょう。
<img width='70%' src='https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/251137/cd125b46-559b-4f62-a493-dfb318fc61a9.png'>

最後に、同じページの上部にある「開発中」をクリックします。
<img width='70%' src='https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/251137/11f9a802-33fe-717c-e8ae-71a60ec53fd5.png'>

「公開」を押下してください。
<img width='70%' src='https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/251137/12d92d67-438c-7c93-677f-4e6c1cb0dc30.png'>

「公開済」になればLINE側の設定は完了です。
<img width='70%' src='https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/251137/7961ebcd-f0e9-be1d-14f3-b3805d03aaf7.png'>

## LIFF IDの設定
先ほどメモした「LIFF ID」をRenderにデプロイしたアプリケーションの環境変数に設定します。
「Environment」から
「Key」に`VITE_LIFF_ID`を
「Value」にメモした「LIFF ID」を設定し、保存します。
保存すると、自動的に再度デプロイされます。
<img width='70%' src='https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/251137/c195a085-ef24-44fe-dd64-d27c9e67ee83.png'>

これでアプリの作成は完了です。

## LIFFアプリへアクセス
LIFF URLにアクセスします。

:::note warn
RenderのURLではなく「`https://liff.line.me~`」で始まるLIFFアプリ用のURLです。
LINEチャネルのLIFFタブから確認できます。
:::

以下のようにログインを求められるのでご自身のアカウントでログインしてください。
<img width='70%' src='https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/251137/6793bff2-dac6-9d9c-4702-6aa6a60200f6.png'>

ログインが完了すると、以下のように取得したユーザー名が表示されます。
<img width='70%' src='https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/251137/3cdcce79-b090-31ae-9415-01b45c99d944.png'>


## まとめ
LIFFアプリを一から作成してデプロイまで持っていくような方法がよくわからなかったので、備忘も兼ねて記事を作成しました。

これだけではまだうまい使い方が思いつきませんが、自分で作成したアプリを簡単にLINEと連携させることができるので、色々便利な使い方が考えられそうです。

次はもっと実践的な内容にチャレンジしてみたいと思いました。