🗂

Next12.2 middleware正式版へ移行

2022/07/01に公開

https://nextjs.org/docs/messages/middleware-upgrade-guide

パッケージアップデートする

npm i next@latest
npm i eslint-config-next@latest --save-dev

ネストされたミドルウェアからシングルルートミドルウェアへ

ベータ版ではルートごとにミドルウェアを適用したい場合に、各ページのディレクトに設置する形態だったが安定板になったことで、一つのミドルウェアで管理する方針となったとのこと。
ベータ版でいまいちだった下記の点を解決するためらしい。

  • ネストすると各ミドルウェアで毎回リクエストや処理が生成されて重複もあるので遅延おきやすいよね
  • コードベースかつ一つのファイルで管理した方が管理しやすそうだよね
  • ファイルベースだと実行順保証しにくいよね

特定のルートにだけ適用したい場合でかつ共通の処理で良いケース

この場合は一つのmiddleware.tsをpagesと同じ階層において、configをmatcherとしてエクスポートしてあげれば、matcherのルートに適合した場合にのみミドルウェアが起動するような形にできるらしい。

middleware.ts
// middleware.ts
import { NextResponse } from 'next/server'
import type { NextRequest } from 'next/server'

export function middleware(request: NextRequest) {
  return NextResponse.rewrite(new URL('/about-2', request.url))
}

// Supports both a single string value or an array of matchers
export const config = {
  matcher: ['/about/:path*', '/dashboard/:path*'],
}

特定のルートでかつ処理が異なるケース

この場合はミドルウェアがマイリクエスト呼ばれる形にはなってしまうけど、条件分岐で対応してねという方針らしい。

middleware.ts
import type { NextRequest } from 'next/server'

export function middleware(request: NextRequest) {
  if (request.nextUrl.pathname.startsWith('/about')) {
    // This logic is only applied to /about
  }

  if (request.nextUrl.pathname.startsWith('/dashboard')) {
    // This logic is only applied to /dashboard
  }
}

middlewareからレスポンスは返せなくなった

beta版ではNextResponseを使うとJsonレスポンスを返せる仕様だったけど、サーバーサイドとクライアントサイドの責務の観点とnextにおけるミドルウェアの責務をリライトとリダイレクトに絞りたいので使えなくしますよとのこと。

Cookieいじる時の方法がかわった

クライアントから来たリクエストやレスポンスに対してミドルウェアでクッキーを操作することができるが、その操作方法をget/setモデルに準拠した形に変えましたとのこと。

廃止

  • cookie
  • clearCookie
  • cookies
    追加
  • cookie.set
  • cookie.delete
  • cookie.getWithOptions

その他

  • userAgentヘルパの追加
  • どのページで呼ばれたかのチェックにURLPatternを使用する方針
  • フレームワーク内部のリクエストでもmiddlewareが呼ばれるように

移行してみた結果

pinoとか使えない
https://nextjs.org/docs/api-reference/edge-runtime#unsupported-apis
→ベータの時はサーバーサイドで動いてるような挙動をしていたけれど、正式にリリースされてEdge Runtimeで動くようになったからなのか?と予想。
Edge Runtimeが何なのかいまいち理解して切れていないのでもう少し掘る必要あり。

axios使ってフェッチしている箇所とかは、fetchadapterを継続して使う必要あり。
Cookieも継続して明示的に設定してあげないとだめ
条件分岐での適応だと割とすぐに汚れそう
middleware関数の中で条件分岐していると具体的な処理を外部関数に逃しても割と見通しが悪い。うまいことハンドリングしてくれてみやすい形態を探した方がよさそう。
体感ちょっぴり速い
buildして本番で試したわけではないけれど、開発環境でも割とネストしていた部分は早くなった、気がする。

まずは正式版の記法で書けたのであとは運用しながら最適化模索していくこととする。

Discussion