🦁
【Next.js】Middleware を宣言的に書く
はじめに
作成したライブラリの宣伝であり、こちらの記事の続編となります。
背景
↑の記事でも書いた通り、 Next.js v12.2 から Middleware が安定版としてサポートされるとともに、 Nested Middleware が廃止されました。
Nested Middleware とは
Nested Middleware というのは、 pages
ディレクトリに _middleware.ts
を置いておくと、表示されるページのパスと同階層以上の _middleware.ts
が実行されるという便利なものでした。
たとえば、以下のようなページ階層になっていて、 /foo/bar
ページを表示する場合は、 ①,② の2つの middleware が発火します。
pages
├── index.tsx
├── _middleware.ts (①)
├── foo
│ ├── index.tsx
│ ├── [id].tsx
│ ├── _middleware.ts (②)
v12.2 以降ではこれらが1つの middleware.ts
に統合されることになります。
つまり、今までの「パスベースで実行する middleware を切り替える」処理を自前で実装し1ファイルに収める必要があります。愚直にやるならば大量の if 文によって構成された手続き型のスクリプトになり、可読性が著しく低下していくことは想像に難くありません。
もしページ構造が複雑で多くの middleware ファイルを pages
に配置していた場合、 v12.2 へのマイグレーション作業は容易なものではないでしょう。
解決策
この移行を助ける & 複雑な middleware を簡単に構成するためのライブラリがこちらです。
- パスと実行したいmiddleware 関数の対応を記述する(宣言的)
- middleware 関数は既存のものとほぼ同じで良い(引数を追加するだけ)
- 複数 middleware の直列実行( middleware を関心毎に分離可能になる)
- 早期 return のサポート
/**
* pages // middleware の実行順序
*├── index.tsx // root1 → root2
*├── foo
*│ ├── index.tsx // root1 → root2 → foo
*│ ├── [id].tsx // root1 → root2 → foo → fooId
*/
export async function middleware(req: NextRequest) {
return composeMiddleware(req, NextResponse.next(), {
scripts: [root1, root2],
'/foo': {
scripts: [fooMiddleware],
'/[id]': [fooIdMiddleware]
}
});
}
詳細はレポジトリをご覧ください。
終わりに
このライブラリによって Next v12.2~ 移行や巨大 middleware によって苦しむ人が少しでも減ることを祈っています。
気が向いた方はレポジトリへのスターよろしくお願いします⭐️
Discussion