Next.js 中間件幫我節(jié)省了數(shù)小時——關(guān)鍵在于這個點子
當初第一次聽說 Next.js Middleware 我心想:“挺酷,但我真的需要嗎?”
結(jié)論:需要。只要你做鑒權(quán)、日志、A/B 測試、重定向里的任意一件,它就像被低估的超能力。
下面是我“開竅”的瞬間、現(xiàn)在的用法,以及它為什么能把頁面邏輯從泥沼里救出來。
什么時候我真的懂了它?
多角色應(yīng)用:管理員 vs 普通用戶。每次用戶訪問受限頁,我都要在頁面/布局里塞:
- 鑒權(quán)
- 條件重定向
- 埋點
- 偶爾 A/B 測試
結(jié)果:臃腫、重復(fù)、到處是 if。換上 middleware 后:一個文件、一個層,入口統(tǒng)一、頁面干凈。
Middleware 到底干啥?
在請求完成前、在邊緣(Edge)就運行你的代碼——在 React 渲染之前先把路清掉。
它放在項目根目錄 **/middleware.ts**(或 .js),像輕量 serverless。
// middleware.ts
import { NextResponse } from 'next/server'
import type { NextRequest } from 'next/server'
export function middleware(request: NextRequest) {
const token = request.cookies.get('token')
if (!token) {
return NextResponse.redirect(new URL('/login', request.url))
}
return NextResponse.next()
}
// ? 在同文件里選擇性匹配
export const config = {
matcher: ['/dashboard/:path*', '/settings/:path*'], // 只對這些路由生效
}
小更正:**路由匹配
matcher應(yīng)該導(dǎo)出在middleware.ts中的config**,而不是next.config.js。
這段小小的中間件就能保護指定路由,不用改任意一個頁面文件。
我真正在用的場景(
用途 | 帶來的好處 |
?? 鑒權(quán)重定向 | 未登錄直送 |
?? A/B 測試 | 基于 Header/Cookie 切不同布局或?qū)嶒?/span> |
?? 地域/語言路由 | 按地區(qū)/語言跳轉(zhuǎn)到對應(yīng)站點或路徑 |
?? 輕量埋點 | 記錄路徑、來源、Session 等入口信息 |
?? 維護模式 | 時間窗內(nèi)屏蔽部分路由或返回占位頁 |
?? Rewrites | 用 |
路由匹配像忍者一樣精準
把匹配寫進 middleware.ts 的 config.matcher,只對需要的頁面生效,避免對靜態(tài)資源、公開頁加負擔。
export const config = {
matcher: [
'/((?!_next/static|_next/image|favicon.ico|public|api/public).*)',
],
}三步上手(今天就能用)
- 創(chuàng)建
middleware.ts - 寫一個簡單鑒權(quán):檢查 Cookie/Session,未登錄重定向
- **加上
config.matcher**:只匹配需要保護/改寫的路由 - 打開瀏覽器,看頁面邏輯瞬間變干凈 ??
進階小技巧
- 讀取請求信息:
request.nextUrl、request.headers、request.cookies - 改寫而非跳轉(zhuǎn):
NextResponse.rewrite(new URL('/internal', request.url))無刷新?lián)Q內(nèi)容 - 追加 Header/Cookie:
response.headers.set(...)、response.cookies.set(...) - A/B 實驗粘性:首次分流后寫入 Cookie,后續(xù)請求保持一致
- 邊緣運行注意:Edge Runtime 沒有 Node 內(nèi)置模塊,盡量少做重 CPU 計算,**<10ms** 收工
什么時候用 Middleware,什么時候別用?
- 該用:入口控制(鑒權(quán)/重定向/國際化/實驗)、輕量埋點、低延遲改寫
- 別用:需要訪問數(shù)據(jù)庫做復(fù)雜業(yè)務(wù);這類邏輯放Route Handler / Server Actions / API 更合適
為什么它像“超能力”
- 頁面更干凈:把“進門檢查”從組件里搬走
- 更快的跳轉(zhuǎn):渲染前就決定去向
- 入口集中化:所有入口規(guī)則一處維護
- 不依賴自建后端:沒有自定義服務(wù)器也能搞定一堆事
一個實用范例(A/B + 登錄保護)
// middleware.ts
import { NextResponse } from 'next/server'
import type { NextRequest } from 'next/server'
export function middleware(req: NextRequest) {
const { nextUrl } = req
const res = NextResponse.next()
const token = req.cookies.get('token')?.value
const isProtected = nextUrl.pathname.startsWith('/app')
// 1) 登錄保護
if (isProtected && !token) {
return NextResponse.redirect(new URL('/login', req.url))
}
// 2) A/B 實驗:缺 cookie 則隨機,寫回 cookie 保持粘性
let bucket = req.cookies.get('ab-home')?.value
if (!bucket) {
bucket = Math.random() < 0.5 ? 'A' : 'B'
res.cookies.set('ab-home', bucket, { path: '/', httpOnly: false })
}
// 3) 根據(jù)實驗分桶改寫到不同頁面
if (nextUrl.pathname === '/' && bucket === 'B') {
return NextResponse.rewrite(new URL('/home-b', req.url))
}
return res
}
export const config = {
matcher: ['/', '/app/:path*'],
}把“進門要做的事”收口到 Middleware,頁面和布局變得專注又輕盈。一個文件,守住所有入口——這就是 Next.js Middleware 的爽點。



























