LIFFをNext.js App Routerで構築する手順
はじめに
LINEヤフー社が提供しているLINE Front-end Framework(以下LIFF
)のアプリを開発するにあたって、
Create LIFF App
という、所謂対話式で環境構築が行えるコマンドを公式が提供しております。
Next.js
を始め、NuxtやSvelteなど多くのライブラリに対応されているのですが、
いざNext.js
で進めると、執筆時点(2024/06/30)ではPage Router向けのセットアップとなってしまいます。
App Routerで使用するには一部自前でセットアップする必要があり、その際に行った手順について記します。
手順
Create LIFF App
を実行する
1. 公式に従い、まずは公式のDocsに従い、npx @line/create-liff-app
を実行して環境構築を行います。
-
Which template do you want to use?
-> Next.js -
Would you like to use App Router?
-> Yes - LIFF IDは事前に用意 & 環境変数に設定してください。
- それ以外はお好みで問題ありません。
ちなみに、npx @line/create-liff-app
の処理実体としては、
create next app
の生成物にcreate liff app
での生成物を加えたのみとなっているようで、処理が交差していることはないように見受けられます。
(これは2で記す生成物からの仮説です。)
参考
- 以降の実例では、以下の選択を前提として行います。
2. インストールされた内容を確認する
以下のような構成になっているかと思います。
この時点では
- Next.jsのApp Router向けのファイル
- From create next app
- LIFFを扱うためのPage Router向けのファイル
- From create liff app
が混ざってしまっているので、全てのファイルをApp Router向けに変更します。
tree -I node_modules
.
├── README.md
├── next-env.d.ts
├── next.config.mjs
├── package.json
├── pages
│ ├── _app.tsx
│ └── index.tsx
├── postcss.config.mjs
├── public
│ ├── favicon.ico
│ ├── next.svg
│ └── vercel.svg
├── src
│ └── app
│ ├── favicon.ico
│ ├── globals.css
│ ├── layout.tsx
│ └── page.tsx
├── styles
│ ├── Home.module.css
│ └── globals.css
├── tailwind.config.ts
├── tsconfig.json
└── yarn.lock
5 directories, 19 files
3. App Routerで扱えるように改修する
まず、LIFFの実体を扱えるようにするReact Context
を定義します。
"use client";
import { Liff } from "@line/liff";
import { createContext } from "react";
type GlobalContextType = {
liff: Liff | null;
liffError: string | null;
};
export const GlobalContext = createContext<GlobalContextType | undefined>(undefined);
次に、こちらのContextを扱いやすくするためにCustom Hook
を用意します。
import { GlobalContext } from "@/contexts/GlobalContext";
import { useContext } from "react";
export const useGlobalContext = () => {
const value = useContext(GlobalContext);
if (!value) {
throw new Error("useGlobalContext must be used within a GlobalContextProvider");
}
return value;
};
次に、src/app/template.tsx
を定義し、pages/_app.tsx
の内容を移行します。
ちなみに、公式にも記載のある移行手順となります。
- コアな処理は自動生成されたものをそのまま移植しています。
-
use client;
を付与してClient Componentとして定義します。 - ReactのContextを使用して、LIFFオブジェクトを渡すようにします。これはLIFFオブジェクトを各ページ要素に渡すために必要です。
"use client";
import { GlobalContext } from "@/contexts/GlobalContext";
import { Liff } from "@line/liff";
import { useCallback, useEffect, useState } from "react";
export default function Template({ children }: { children: React.ReactNode }) {
const [liffObject, setLiffObject] = useState<Liff | null>(null);
const [liffError, setLiffError] = useState<string | null>(null);
// Execute liff.init() when the app is initialized
useEffect(() => {
// to avoid `window is not defined` error
import("@line/liff")
.then((liff) => liff.default)
.then((liff) => {
console.log("LIFF init...");
liff
.init({ liffId: process.env.NEXT_PUBLIC_LIFF_ID! })
.then(() => {
console.log("LIFF init succeeded.");
setLiffObject(liff);
})
.catch((error: Error) => {
console.log("LIFF init failed.");
setLiffError(error.toString());
});
});
}, []);
return (
<GlobalContext.Provider value={{ liff: liffObject, liffError: liffError }}>
<div>{children}</div>
</GlobalContext.Provider>
);
}
最後に、pages
ディレクトリを削除します。
※pages/index.tsx
の内容で特に引き継ぐものはありません。
4. 3で作成したLIFFのモジュールをPage Componentに組み込む
src/hooks/useGlobalContext.ts
を組み込み、各ページで扱えるようにセットアップします。
注意点としては、Clientで動作させる前提となるため、Client Component
内で呼び出す必要があります。
ここではサンプルとして、src/app/_components/Liff.tsx
というClient Component
を作成し、そちら経由でContextを呼び出してみます。
"use client";
import { useGlobalContext } from "@/hooks/useGlobalContext";
import { FC } from "react";
export const Liff:FC = () => {
const { liff, liffError } = useGlobalContext();
return (
<div>
<h2>create-liff-app</h2>
{liff && <p>LIFF init succeeded.</p>}
{liffError && (
<>
<p>LIFF init failed.</p>
<p>
<code>{liffError}</code>
</p>
</>
)}
<a
href="https://developers.line.biz/ja/docs/liff/"
target="_blank"
rel="noreferrer"
>
LIFF Documentation
</a>
</div>
);
}
次に、src/app/page.tsx
を以下のように変更します。
import { Liff } from "@/app/_components/Liff";
export default function Home() {
return (
<main>
<Liff />
</main>
);
}
5. 動作確認
Next.jsを起動し、/
のパスを開きます。
以下のような表記になれば疎通成功です。
お持ちのLINEチャンネルに組み込んで、開発を進めましょう。
余談
- この記事ではTailwind CSSを選択しておりますが、create liff appで生成される内容はCSS Modulesのファイルとなっております。CSSライブラリの移行に関しては特に特記事項もなく、ここでは割愛しております。
- create liff appではパッケージ管理ツールとして
npm
かyarn
しか執筆時点では選択できませんが、pnpm
などへの移行も一般的な手順で可能です。(私は実際にpnpm
を使用して開発を進めています)
後書き
App Routerは日々進化しているので、どんどん使っていきたいですね🙏
ご意見、ご提案などがございましたらお気軽にコメントいただけたら嬉しいです!
Discussion