中介軟體 (Middleware)
中介軟體 (Middleware) 允許您在請求完成前執行程式碼。然後,根據傳入的請求,您可以透過重寫、重新導向、修改請求或回應標頭,或直接回應來修改回應。
中介軟體會在快取內容和路由匹配之前執行。詳情請參閱 路徑匹配。
使用情境
將中介軟體整合到您的應用程式中可以顯著提升效能、安全性和使用者體驗。以下是一些中介軟體特別有效率的常見情境:
- 身份驗證與授權 (Authentication and Authorization):在授予特定頁面或 API 路由的存取權限前,確保使用者身份並檢查 session cookies。
- 伺服器端重新導向 (Server-Side Redirects):根據特定條件(例如語言區域、使用者角色)在伺服器層級重新導向使用者。
- 路徑重寫 (Path Rewriting):根據請求屬性動態重寫 API 路由或頁面的路徑,以支援 A/B 測試、功能發布或舊版路徑。
- 機器人偵測 (Bot Detection):透過偵測和阻擋機器人流量來保護您的資源。
- 記錄與分析 (Logging and Analytics):在頁面或 API 處理之前,擷取並分析請求資料以獲得洞察。
- 功能標記 (Feature Flagging):動態啟用或停用功能,以實現無縫功能發布或測試。
識別中介軟體可能不是最佳解決方案的情境同樣重要。以下是一些需要注意的情境:
- 複雜的資料擷取與操作 (Complex Data Fetching and Manipulation):中介軟體不適用於直接資料擷取或操作,這應在路由處理程式 (Route Handlers) 或伺服器端工具中完成。
- 繁重的計算任務 (Heavy Computational Tasks):中介軟體應輕量且快速回應,否則可能導致頁面載入延遲。繁重的計算任務或長時間執行的程序應在專用的路由處理程式中完成。
- 廣泛的 session 管理 (Extensive Session Management):雖然中介軟體可以管理基本的 session 任務,但廣泛的 session 管理應由專用的身份驗證服務或在路由處理程式中管理。
- 直接資料庫操作 (Direct Database Operations):不建議在中介軟體中執行直接資料庫操作。資料庫互動應在路由處理程式或伺服器端工具中完成。
慣例
在專案根目錄中使用 middleware.ts
(或 .js
) 檔案來定義中介軟體。例如,與 pages
或 app
同層級,或在適用的情況下放在 src
目錄內。
注意:雖然每個專案僅支援一個
middleware.ts
檔案,但您仍然可以模組化組織中介軟體邏輯。將中介軟體功能拆分到獨立的.ts
或.js
檔案中,並將它們匯入到主要的middleware.ts
檔案中。這樣可以更清晰地管理特定路由的中介軟體,並在middleware.ts
中集中控制。透過強制使用單一中介軟體檔案,可以簡化配置、避免潛在衝突,並透過避免多層中介軟體來優化效能。
範例
路徑匹配
中介軟體會針對專案中的每個路由被調用。因此,使用匹配器 (matcher) 來精確定位或排除特定路由至關重要。以下是執行順序:
next.config.js
中的headers
next.config.js
中的redirects
- 中介軟體 (
rewrites
、redirects
等) next.config.js
中的beforeFiles
(rewrites
)- 檔案系統路由 (
public/
、_next/static/
、pages/
、app/
等) next.config.js
中的afterFiles
(rewrites
)- 動態路由 (
/blog/[slug]
) next.config.js
中的fallback
(rewrites
)
有兩種方式可以定義中介軟體將在哪些路徑上執行:
匹配器 (Matcher)
matcher
允許您過濾中介軟體以在特定路徑上執行。
您可以使用陣列語法匹配單一路徑或多個路徑:
matcher
配置允許完整的正規表示式,因此支援如負向預查 (negative lookaheads) 或字元匹配等操作。以下是一個負向預查的範例,用於匹配除特定路徑外的所有路徑:
您也可以透過使用 missing
或 has
陣列,或兩者的組合,來繞過中介軟體處理某些請求:
須知:
matcher
值必須是常數,以便在構建時進行靜態分析。動態值(如變數)將被忽略。
配置的匹配器:
- 必須以
/
開頭 - 可以包含命名參數:
/about/:path
匹配/about/a
和/about/b
,但不匹配/about/a/c
- 可以在命名參數上使用修飾符(以
:
開頭):/about/:path*
匹配/about/a/b/c
,因為*
表示 零個或多個。?
表示 零個或一個,+
表示 一個或多個 - 可以使用括號包裹的正規表示式:
/about/(.*)
與/about/:path*
相同
詳情請參閱 path-to-regexp 文件。
須知:為了向後兼容,Next.js 始終將
/public
視為/public/index
。因此,/public/:path
的匹配器將會匹配。
條件陳述式
NextResponse
NextResponse
API 允許您:
- 將傳入的請求
redirect
到不同的 URL - 透過顯示給定的 URL 來
rewrite
回應 - 為 API 路由、
getServerSideProps
和rewrite
目的地設定請求標頭 - 設定回應 cookies
- 設定回應標頭
要從中介軟體產生回應,您可以:
使用 Cookies
Cookies 是常規的標頭。在 Request
中,它們儲存在 Cookie
標頭中。在 Response
中,它們儲存在 Set-Cookie
標頭中。Next.js 透過 NextRequest
和 NextResponse
上的 cookies
擴充功能,提供了一種方便的方式來存取和操作這些 cookies。
- 對於傳入的請求,
cookies
提供以下方法:get
、getAll
、set
和delete
cookies。您可以使用has
檢查 cookie 是否存在,或使用clear
移除所有 cookies。 - 對於傳出的回應,
cookies
提供以下方法:get
、getAll
、set
和delete
。
設定標頭
您可以使用 NextResponse
API 設定請求和回應標頭(自 Next.js v13.0.0 起支援設定 請求 標頭)。
須知:避免設定過大的標頭,因為根據後端網頁伺服器的配置,可能會導致 431 請求標頭欄位過大 錯誤。
CORS
您可以在中介軟體 (Middleware) 中設定 CORS 標頭來允許跨來源請求,包括簡單請求和預檢請求。
小知識: 您可以在路由處理程式 (Route Handlers) 中為個別路由設定 CORS 標頭。
產生回應
您可以直接從中介軟體返回 Response
或 NextResponse
實例來產生回應。(此功能自 Next.js v13.1.0 起可用)
waitUntil
與 NextFetchEvent
NextFetchEvent
物件繼承了原生的 FetchEvent
物件,並包含 waitUntil()
方法。
waitUntil()
方法接受一個 promise 作為參數,並延長中介軟體的生命週期直到該 promise 完成。這對於在背景執行工作非常有用。
進階中介軟體標記
在 Next.js v13.1
版本中,新增了兩個中介軟體標記 skipMiddlewareUrlNormalize
和 skipTrailingSlashRedirect
來處理進階使用案例。
skipTrailingSlashRedirect
停用 Next.js 用於新增或移除尾部斜線的重新導向。這允許在中介軟體中自訂處理方式,為某些路徑保留尾部斜線而不為其他路徑保留,這可以使漸進式遷移更加容易。
skipMiddlewareUrlNormalize
允許停用 Next.js 中的 URL 標準化,使直接訪問和客戶端轉換的處理方式相同。在某些進階案例中,此選項透過使用原始 URL 提供完整控制。
執行環境
中介軟體目前僅支援 Edge 執行環境,無法使用 Node.js 執行環境。