🌟
Next.jsのMiddlewareと友達になろう
導入
「middlewareって何?」、「重要なんだろうけど学ぶ気にならない」その人たちのための記事です。この記事を読めばmiddlewareと友達になれます。途中コードもありますが、必ず手を動かして、コードを写して読みましょう。「このコード使わなそう」と思っても書きましょう。いつか、そのコードと出会う日が来るでしょう。
middlewareとは
httpのrequestが終わる前に実行される。requestの内容によって、responseやrequest,response headersを修正する。middlewareは、cacheされる前、routeがマッチする前に実行される。
メリット
middlewareを使うことで、パフォーマンス、セキュリティ、ユーザ体験(その製品を使った時の満足度)が上がる
middlewareが効果的な場面
場面 | 情報 |
---|---|
認証機能(auth) | 他のページやapiルートにアクセスする前にユーザ情報やセッションを確認 |
server-sideリダイレクト | ユーザの役割など、状況に応じてリダイレクトするとき |
パスの書き換え | requestに基づいてページやAPIルートを動的に書き換えるとき |
Bot Detection | リソースを保護する |
loggingと分析 | ページやAPIルートに進む前に、requestデータを分析する |
middlewareが効果的ではない場面
場面 | 情報 |
---|---|
複雑なデータのfetch | middlewareは直接的なデータのfetchのために作られていない。そのような処理は、route handlersやserver utilitiesで行う |
重い処理 | middlewareは軽くてレスポンスが素早いものであるべき。重い処理は、route handlersで行うべき |
広範囲なセッション管理 | middlewareは基本的なセッション管理はできるが、広範囲な管理は、認証サービスやroute handlersで管理するべき |
データベースの操作 | データベースの操作は、route handlersやserver utilitiesが行うべき |
Matching Paths
middlewareは、すべてのルートに対して呼び出される(requestが終わる前に実行されるから)。ただ、matchersを使えば、特定のルートに対して実行させることができる。
middleware.ts
export const config={
matcher:['/about/:path','/dashboard/:path']
}
以下の例は、api,_next/static(staticファイル),_next/image(image optimizationファイル)、favicon.ico(faviconファイル)以外のファイルに対して、middlewareを実行させるコードである。
middleware.ts
export const config={
matcher:[
'/((?!api|_next/static|_next/image|favicon.ico).*)',
]
}
条件文
middleware.ts
import {NextResponse} from 'next/server'
import type {NextRequest} from 'next/server'
export function middleware(request:NextRequest){
if(request.nextUrl.pathname.startsWith('/about')){
return NextResponse.rewrite(new URL('/about-2',request.url))
}
if(request.nextUrl.pathname.startsWith('/dashboard')){
return NextResponse.rewrite(new URL('/dashboard/user',request.url))
}
}
middlewareでcookiesを使う
NextRequestが出てきますが、その説明は以下の記事を見てください
middleware.ts
import {NextResponse} from 'next/server'
import type {NextRequest} from 'next/server'
export function middleware(request:NextRequest){
let cookie=request.cookies.get('nextjs')
console.log(cookie) // {name:'nextjs',value:'fast',Path:'/'}
console.log(allCookies) //[{name:'nextjs',value:'fast'}]
request.cookies.has('nextjs') //true
request.cookies.delete('nextjs')
request.cookies.has('nextjs') //false
const response=NextResponse.next()
response.cookies.set('vercel','fast')
response.cookies.set({
name:'vercel',
value:'fast',
path:'/',
})
cookie=response.cookie.get('vercel')
console.log(cookie) //{name:'vercel',value:'fast',Path:'/'}
return response
}
Headersを設定する
middleware.ts
import { NextResponse } from 'next/server'
import type { NextRequest } from 'next/server'
export function middleware(request:NextRequest){
const requestHeaders=new Headers(request.headers)
//headerをコピーして、新しいheaderを設定
requestHeaders.set('x-hello-from-middleware1','hello')
//NextResponseのrewriteを使用してheaderを書き換えることもできる
const response=NextResponse.next({
request:{
headers:requestHeaders,
}
})
response.headers.set('x-hello-from-middleware2','hello')
return response
}
注意事項として、重いheaderは書かない。middlewareの役割に反するから。
まとめ
middlewareは、軽くて素早い処理に使う
重い処理は、route handlersやserver utilitiesに任せるべき
参考文献
Discussion