LIFF CLIのserveコマンドを最速で徹底解説する

## はじめに
[前回の記事](https://qiita.com/course_k/items/cdc67650601e8b137389)で、新しく発表された**LIFF CLI**についての解説記事を書きました。

それから約2ヶ月、待望のアップデートが来たので、その中身について解説していきます。

リリースから5日経過していますが、Qiita上では現時点で解説記事は存在していないようなので、今回も本記事が最速での解説になるかと思います。

### 前提条件
本記事では以下の2つを前提として進めます。
* 何らかのLIFFアプリを構築済であること
→LIFFアプリをお試しで作るだけなら[こちらの記事](https://qiita.com/course_k/items/3d34871becf281870b5c)が参考になるかと思います。
* liff-cliを導入済みであること
→導入は[前回の記事](https://qiita.com/course_k/items/cdc67650601e8b137389#%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88%E3%83%BC%E3%83%AB)を参考にしてください。
## 新機能 serveコマンド
### 概要
今回のリリースで新しく追加されたのは`serve`コマンドです。
このコマンドを使用することで、以下の2点が可能になりました。
* ローカル開発環境をhttpsで起動する
* LIFFアプリのデバッグを行う

リリースの詳細は以下から確認できます。

https://developers.line.biz/ja/news/2024/09/24/liff-cli-0-2-0/

:::note alert
実行するのはお試し用のLIFFアプリにしてください。
`serve`コマンドを実行するとLIFFアプリのエンドポイントURLが書き換わり、正しくアクセスできなくなるためです。

実行前
<img width='80%' src='https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/251137/1c74a97d-d143-fa96-3258-09b8fa555262.png'>

実行後
<img width='80%' src='https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/251137/ea835d45-fb80-a2ae-e0db-9a23212f4506.png'>

:::

### ローカル開発環境をhttpsで起動
#### 事前準備
httpsで起動するにはSSL証明書が必要なので、まずはその準備をします。

:::note warn
https、およびsslについてあまり詳しくないため、表現に誤りがあるかもしれません。
あくまでもローカルでお試しするための方法としてお使いください。
:::

SSL証明書の生成のために、`mkcert`を使用します。
私の環境ではMacを使用しているので、`homebrew`を使用して以下の通り導入しました。
```bash
brew install mkcert
```

その他の環境での`mkcert`の導入方法は以下を参考にしてください。

https://github.com/FiloSottile/mkcert?tab=readme-ov-file#installation

次に、`mkcert`を使用してローカルの認証局を作成します。
```bash
mkcert --install
```
管理者パスワードを求められます。
<img width='80%' src='https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/251137/99d96074-9727-eeeb-f10f-d28b72090990.png'>

作成が完了すると、以下のように表示されます。
これで、証明書の生成ができるようになりました。
<img width='80%' src='https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/251137/2021ef85-4cf9-59f1-9abf-3a1a3ed629e0.png'>

liffアプリのルートディレクトリに移動し、localhostの証明書と秘密鍵を生成します。
```bash
cd liffアプリのルートディレクトリ
mkcert localhost
```
コマンドを実行したディレクトリに証明書（localhost.pem）と秘密鍵（localhost-key.pem）が生成されました。
<img width='80%' src='https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/251137/f6c60273-c73f-2207-6ff6-3dca8809bc8e.png'>

以下の通り、ファイルが生成されているのがわかります。
<img width='80%' src='https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/251137/2c7a7f1f-ac19-c8d6-0e96-984d3a2bf311.png'>

ここまでで事前準備は完了です。

#### serveコマンドの実行
実行方法は2つあります。

以下のように、urlを指定する方法と
```bash
liff-cli serve --liff-id liffId --url http://localhost:5173/
```

以下のようにhostとportを指定する方法です。
```bash
liff-cli serve --liff-id 2005506682-7Am0vbZQ --host localhost --port 5173
```

どちらも実行結果は変わりません。

それぞれオプションについて確認します。

##### liff-id
LIFFアプリのLIFF IDを指定します。
注意点が1つあり、指定するのはデフォルトチャネルに紐づくLIFFアプリのLIFF IDである必要があります。

###### デフォルトチャネルと対応方法
デフォルトチャネルとは、LIFF CLIのコマンドを実行するうえで、チャネルIDを省略した際に使用されるチャネルを指します。

`app`コマンドでは、オプションで`channel-id`が用意されていますが、`serve`コマンドにはありません。
よって、`serve`コマンド実行時には、デフォルトチャネルが使用されるようです。

2024/9/29現在、デフォルトチャネルが何かを確認する手段がありません。
よって、指定するLIFF IDが適切なものか判定するには、以下の2つのいずれかがよいでしょう。

(1) デフォルトチャネルを指定する
どれがデフォルトかわからないので、`serve`コマンド実行前に指定したいLIFFアプリが紐づいているチャネルを登録します。
以下のように、`channel use`コマンドを使うことで指定できます。
```bash
liff-cli channel use channelID
```

:::note warn
デフォルトチャネルに指定するためには、まず`channel add`コマンドでチャネルを登録しておく必要があります。
:::
(2) LIFFアプリの一覧を確認する
`app list`コマンドをチャネルIDを省略して実行することで、デフォルトチャネルに紐づくLIFFアプリの一覧を確認することができます。
```bash
liff-cli app list
```

これにより、`serve`コマンドで指定したいLIFF IDが表示されればOKということになります。
もし表示されないようなら、デフォルトチャネルが別のチャネルであるので、先ほどの`channel use`コマンドでデフォルトチャネルを変更します。

##### url
ローカルで起動するLIFFアプリのURLです。

##### host
ローカルで起動するLIFFアプリのホストです。
基本的にローカルで実行しているので、`localhost`で固定になるかと思います。

##### port
ローカルで起動するLIFFアプリのポート番号です。
私はViteを使用しているので5173ですが、各々の環境によって異なると思います。

`url`または`host`、`port`の組み合わせによって、httpsで起動したいローカルのLIFFアプリを指定します。

##### local-proxy-port
省略可能なオプションです。
httpsで起動するローカルのアプリのポート番号を指定できます。
省略した場合は9000になります。

もう一つ省略可能なオプションがありますが、デバッグの解説時に扱います。

#### 実行結果
コマンドを実行すると、LIFFアプリのURLと、httpsでアクセスできるローカル用のURLが表示されます。
<img width='100%' src='https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/251137/8e3e7813-583a-c4a7-8272-052d2c335a0c.png'>

ローカル用のURLにアクセスすると、以下のように表示されました。
<img width='80%' src='https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/251137/e02c1e15-c948-9b71-3602-56958a8bb594.png'>

httpsで起動できています。
<img width='80%' src='https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/251137/e9ce478b-a921-6475-89ef-80024a4d2a2b.png'>

参考までに、以下は通常のローカル起動の例です。
<img width='80%' src='https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/251137/4dc7f48e-68e9-a465-593e-e3b0a3b082e4.png'>

`serve`コマンドを使うことで、httpsでローカル上にアプリを立ち上げることができました。

### LIFFアプリのデバッグ
`serve`コマンドには省略可能なオプションがもう一つあります。
それが`inspect`です。

これを指定することで、LIFF Inspectorが起動します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/251137/193c6af9-5ca3-375c-e4af-92bc2f96828d.png)

LIFF InspectorはLIFFアプリをデバッグするためのLIFFプラグインで、未導入の場合には`inspect`オプション指定時に上記のようにインストールするか確認してくれます。

インストールが完了すると、以下のようにデバッグが可能になります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/251137/ac7b612a-b8fa-0e75-2ad8-850cdb7db726.png)

LIFF URLにアクセスすると、`serve`コマンドを実行したターミナルにdevtools://devtools/から始まるURLが表示されます。このURLをGoogle Chromeで開くと、LIFFアプリをGoogle Chrome上でデバッグできます。

と公式サイトには記載がありましたが、現時点で私はうまく動かすことができませんでした。

以下のように、ワーニングが表示されています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/251137/a9c2ad3d-d68b-0b70-9a3a-b03c7699b4cb.png)

各ツールのバージョンはLIFF CLIの推奨バージョンであることは確認しているんですが、おそらく私の環境起因かと思いますので、ここについては再度検証してから追記します。

適切な挙動については以下の公式サイトから確認できます。

https://developers.line.biz/ja/docs/liff/liff-cli/#serve-inspect


## まとめ
最後の部分について、現時点で最後まで解説することができませんでしたが、serveについて学ぶことができました。

おそらく、最後のLIFF Inspectorのために用意された機能なのかなと思いました。
LIFF InspectorはSSL/TLSで暗号化されている必要があるらしく、`serve`コマンドによりhttpsで起動できるため、LIFF Inspectorの導入がスムーズになるな、と感じました。

詳細はLIFF InspectorのREAD MEに記載があります。

https://github.com/line/liff-inspector/blob/main/README_ja.md#%E9%87%8D%E8%A6%81-liff-inspector-server-%E3%81%AF-ssltls-%E3%81%A7%E6%9A%97%E5%8F%B7%E5%8C%96%E3%81%95%E3%82%8C%E3%82%8B%E5%BF%85%E8%A6%81%E3%81%8C%E3%81%82%E3%82%8A%E3%81%BE%E3%81%99

LIFFのプラグインであるLIFF Inspectorについては全然触れてきていなかったので、うまくいかなかった部分の検証も含めて、別途記事を書きたいなと思っています。