Featured image of post Next.js 中間件:路由、驗證和邊緣運算Featured image of post Next.js 中間件:路由、驗證和邊緣運算

Next.js 中間件:路由、驗證和邊緣運算

深入研究 Next.js 中間件的路由、驗證、邊緣運算、地理位置、A/B 測試和邊緣運行時限制。

介紹

Next.js 中間件在每個請求之前執行,在邊緣或無伺服器區域運行。專案根目錄下的單一 middleware.ts 檔案會攔截傳入要求,並且可以在請求到達匹配路由之前重定向、重寫、操作標頭或執行驗證檢查。

中間件非常適合在頁面渲染之前進行快速、基於邊緣的決策。預設情況下,它不在靜態資源或 _next/static 上運作。

基本結構

中間件檔案匯出一個接收 NextRequest 並傳回 NextResponse 的函數,以及定義哪些路徑觸發執行的 config 物件。

import { NextResponse } from "next/server";
import type { NextRequest } from "next/server";

export function middleware(request: NextRequest) {
  console.log(`Request: ${request.nextUrl.pathname}`);
  return NextResponse.next();
}

export const config = {
  matcher: ["/((?!api|_next/static|_next/image|favicon.ico).*)"],
};

matcher 配置使用帶有負向前瞻的路徑到正規表示式語法來排除靜態檔案。對於特定於部分的中間件,請使用多種模式,例如 ['/dashboard/:path*', '/admin/:path*']


認證與授權

在中間件中處理身份驗證優於每頁檢查,因為它提供了單一事實來源並消除了頁面轉換時的閃爍。

export function middleware(request: NextRequest) {
  const token = request.cookies.get("session")?.value;
  const { pathname } = request.nextUrl;

  if (!token && pathname.startsWith("/dashboard")) {
    return NextResponse.redirect(new URL("/login", request.url));
  }

  if (token && pathname.startsWith("/login")) {
    return NextResponse.redirect(new URL("/dashboard", request.url));
  }

  return NextResponse.next();
}

對於基於角色的訪問,請在允許訪問管理路由之前解碼 JWT 或會話令牌並檢查使用者的角色。 NextAuth.js、Clerk 和 Auth0 都提供了簡化此過程的中間件助手。


請求重寫和重定向

中間件支援兩種類型的 URL 操作。重寫可在不更改瀏覽器 URL 的情況下提供不同的內容,而重定向則完全更改 URL。

export function middleware(request: NextRequest) {
  const { pathname, hostname } = request.nextUrl;

  const tenant = hostname.split(".")[0];
  if (tenant && tenant !== "www") {
    request.nextUrl.pathname = `/${tenant}${pathname}`;
    return NextResponse.rewrite(request.nextUrl);
  }
}

常見用例包括本地化登陸頁面、功能門控內容以及基於子網域或 cookie 值的多租用戶路由。


地理位置和個性化

邊緣中間件透過 request.geo 提供地理位置數據,包括城市、國家、地區、緯度和經度。 request.ip 屬性給予客戶端 IP 位址。

export function middleware(request: NextRequest) {
  const { country } = request.geo;
  const { pathname } = request.nextUrl;

  if (["DE", "FR", "IT", "ES", "NL"].includes(country) && !pathname.startsWith("/gdpr")) {
    return NextResponse.redirect(new URL("/gdpr", request.url));
  }

  return NextResponse.next();
}

地方定價、內容本地化和 GDPR 同意路由都是基於地理位置的中間件邏輯的實際應用。


邊緣運轉時限制

中間件運行在 Edge Runtime 上,它有重要的限制:

限制詳情
Node.js API不可用(無檔案系統、加密、路徑)
最大執行30 秒(目標是 1 秒以內)
捆綁尺寸1 MB 限制(程式碼加上依賴項)
資料庫無直接聯繫;使用 API 路由

保持中間件邏輯精簡。使用 API 路由或伺服器元件進行繁重的運算、資料庫存取或檔案系統操作。


結論

使用中間件進行快速、基於邊緣的決策,例如身份驗證、重定向和 URL 重寫。保持邏輯簡單,因為它在每個匹配的請求上運行。為了效能,優先使用 matcher 配置而不是函數內部的條件檢查。使用 Playwright 或 Cypress 等工具將中介軟體行為與頁面邏輯分開測試。