一文搞懂Next.js中Proxy的使用
在 Next.js 中,“Proxy” 這個概念實際上指向兩個不同層面但同樣重要的功能:一個是 Next.js 15 之后內(nèi)置的、運行在邊緣網(wǎng)絡(luò)上的請求攔截器(原 Middleware),另一個則是通過配置文件實現(xiàn)的、用于轉(zhuǎn)發(fā) API 請求的 Rewrites 代理。
簡單來說,前者像是應(yīng)用的門衛(wèi),后者則像是應(yīng)用的傳話員。
為了幫你更清晰地理解,我把它們的核心區(qū)別整理成了一個表格:
| 特性 | 內(nèi)置 proxy (原 Middleware) | 配置 rewrites (反向代理) |
|---|---|---|
| 核心定位 | 在請求到達頁面之前,運行自定義代碼進行攔截和處理。 | 將請求從一個路徑“映射”到另一個路徑(可以是內(nèi)部或外部URL),對客戶端透明。 |
| 主要用途 | 鑒權(quán)、A/B測試、國際化、日志記錄、修改請求/響應(yīng)頭。 | 解決跨域問題、隱藏真實API地址、將舊站點路由平滑過渡到新應(yīng)用、集成第三方服務(wù)。 |
| 運行時機 | 在 redirects 之后,beforeFiles rewrites 之前。 | 有三種時機:beforeFiles, afterFiles, fallback,可以在文件系統(tǒng)(頁面/靜態(tài)文件)檢查前后執(zhí)行。 |
| 代碼位置 | 項目根目錄下的 proxy.ts 或 proxy.js 文件。 | next.config.js 文件中的 async rewrites() 函數(shù)。 |
| 能力范圍 | 可以編程式地返回 NextResponse,實現(xiàn) redirect, rewrite, 或直接響應(yīng)。 | 聲明式地配置 source 和 destination 映射關(guān)系,支持復雜的路徑匹配規(guī)則。 |
深入理解:內(nèi)置proxy(原 Middleware)
從 Next.js 15 開始,原來的 middleware 文件被重命名為 proxy,其功能保持不變。你可以把它想象成一個在服務(wù)器上運行、在用戶請求到達頁面之前的“檢查站”。
關(guān)鍵特性與能力 在 proxy 函數(shù)中,你可以訪問 NextRequest 對象,并通過返回 NextResponse 來實現(xiàn)多種操作:
- 重寫(Rewrite):在服務(wù)端將請求映射到另一個 URL,但客戶端瀏覽器地址欄的 URL 不會改變。這非常適合做 A/B 測試或在同一個域名下托管不同版本的應(yīng)用。
// proxy.ts import { NextResponse } from 'next/server' import type { NextRequest } from 'next/server' export function proxy(request: NextRequest) { if (request.nextUrl.pathname.startsWith('/about')) { // 訪問 /about 的用戶,實際看到的是 /about-2 頁面的內(nèi)容 return NextResponse.rewrite(new URL('/about-2', request.url)) } } - 重定向(Redirect):將請求引導至另一個 URL,瀏覽器地址欄會更新。適用于用戶登錄校驗或永久移動的頁面。
// proxy.ts import { NextResponse } from 'next/server' import type { NextRequest } from 'next/server' export function proxy(request: NextRequest) { if (!isLoggedIn(request)) { // 未登錄用戶訪問 dashboard 時,跳轉(zhuǎn)到登錄頁 return NextResponse.redirect(new URL('/login', request.url)) } } - 操作頭信息與 Cookie:可以讀取、設(shè)置或刪除請求頭和響應(yīng)頭,以及 Cookie,用于實現(xiàn)功能開關(guān)、用戶追蹤等。
- 直接響應(yīng):甚至可以直接在
proxy層返回一個響應(yīng)體,而不需要經(jīng)過頁面渲染,比如返回一個簡單的robots.txt或維護頁面。
- 重寫(Rewrite):在服務(wù)端將請求映射到另一個 URL,但客戶端瀏覽器地址欄的 URL 不會改變。這非常適合做 A/B 測試或在同一個域名下托管不同版本的應(yīng)用。
配置與執(zhí)行
proxy默認會作用于所有路由,因此強烈建議通過導出的config對象中的matcher選項來精確控制其生效路徑,以優(yōu)化性能。// proxy.ts export const config = { matcher: [ /* * 匹配所有除了以這些開頭的路徑: * - api (API routes) * - _next/static (靜態(tài)文件) * - _next/image (圖片優(yōu)化文件) * - favicon.ico, sitemap.xml (靜態(tài)資源文件) */ '/((?!api|_next/static|_next/image|favicon.ico|sitemap.xml).*)', ], }
深入理解:配置rewrites(反向代理)
rewrites 是定義在 next.config.js 中的一個異步函數(shù),它更像是一種“聲明式”的代理規(guī)則。它告訴 Next.js 服務(wù)器:“當用戶請求路徑 A 時,你悄悄地替我去路徑 B 拿到內(nèi)容,然后返回給用戶。”
核心價值與場景
- 解決跨域(CORS):這是開發(fā)中最常見的用途。通過將前端對
/api的請求,在 Next.js 服務(wù)端轉(zhuǎn)發(fā)到真實的后端 API 地址(如https://api.example.com),從而繞過了瀏覽器的同源策略。// next.config.js module.exports = { async rewrites() { return [ { source: '/api/:path*', // 前端請求的路徑 destination: 'https://api.example.com/:path*', // 實際轉(zhuǎn)發(fā)的后端地址 }, ] }, } - 集成第三方服務(wù):可以隱藏第三方服務(wù)的真實地址,將其“包裝”成自己域名下的接口,避免被廣告 屏 蔽器攔截,同時也更安全。
- 平滑遷移:當你將舊站點逐步遷移到 Next.js 時,可以用
fallback類型的rewrites,讓所有不存在的頁面都 fallback 到舊站點,實現(xiàn)漸進式重構(gòu)。
- 解決跨域(CORS):這是開發(fā)中最常見的用途。通過將前端對
三種執(zhí)行時機
rewrites函數(shù)可以返回一個對象,包含三種數(shù)組,它們在不同的時機執(zhí)行,提供了極大的靈活性:- beforeFiles:在檢查 public 目錄下的靜態(tài)文件和頁面路由之前執(zhí)行??梢杂脕砀采w某些特定頁面。
- afterFiles:在檢查完靜態(tài)文件和頁面路由之后,但在動態(tài)路由(如 pages/[slug].js)之前執(zhí)行。
- fallback:在所有路由(包括動態(tài)路由)都沒有匹配到之后,返回 404 頁面之前執(zhí)行。非常適合作為“最后一道防線”代理到舊系統(tǒng)。
高級匹配規(guī)則
rewrites的source路徑支持參數(shù)化和正則表達式,并能根據(jù)has或missing條件(如特定的 header、cookie 或 query 參數(shù))來決定是否應(yīng)用。// next.config.js module.exports = { async rewrites() { return [ { source: '/blog/:slug', destination: '/news/:slug', // 將 /blog/hello 轉(zhuǎn)發(fā)到 /news/hello }, { source: '/old/:path*', destination: 'https://legacy-site.com/:path*', // 代理到外部 URL }, { source: '/admin/:path*', has: [{ type: 'cookie', key: 'authorized', value: 'true' }], destination: '/dashboard/:path*', // 只有攜帶特定 cookie 時才轉(zhuǎn)發(fā) }, ] }, }
總結(jié)與選擇指南
簡單來說,如何選擇取決于你的業(yè)務(wù)邏輯:
- 如果你的邏輯是編程式的、條件復雜的、需要讀取或修改請求/響應(yīng)頭,例如“檢查用戶是否登錄,未登錄就跳轉(zhuǎn)”,那么請使用
proxy。 - 如果你的邏輯是聲明式的、純粹的路徑映射,例如“將所有
/api請求轉(zhuǎn)發(fā)到另一個服務(wù)器來解決跨域問題”,那么請使用rewrites。
在開發(fā)環(huán)境中,rewrites 通常是解決 API 跨域問題的最簡單、最標準的方法。而在生產(chǎn)環(huán)境中,雖然 rewrites 也可以作為反向代理,但更常見的做法是在 Next.js 應(yīng)用前面再加一層專業(yè)的反向代理服務(wù)器(如 Nginx),來處理負載均衡、SSL 終端和安全防護等更底層的網(wǎng)絡(luò)問題。
到此這篇關(guān)于一文搞懂Next.js中Proxy的使用的文章就介紹到這了,更多相關(guān)Next.js Proxy內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
uniapp自定義頁面跳轉(zhuǎn)loading的實現(xiàn)代碼
有些頁面加載起來比較慢,為了加強用戶體驗效果,所以一般都會做一個頁面加載等待的提示,頁面加載完成后消失,下面這篇文章主要給大家介紹了關(guān)于uniapp自定義頁面跳轉(zhuǎn)loading的實現(xiàn)代碼,需要的朋友可以參考下2023-06-06
JS實現(xiàn)1000以內(nèi)被3或5整除的數(shù)字之和
今天在技術(shù)群里看到一道這樣的提:求1000以內(nèi)被3或5整除的數(shù)字之和。小編把我的解決辦法分享到腳本之家平臺,供大家參考2016-02-02
js獲取iframe中的window對象的實現(xiàn)方法
下面小編就為大家?guī)硪黄狫S獲得iframe中的window對象的實現(xiàn)方法。小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2016-05-05
Javascript添加監(jiān)聽與刪除監(jiān)聽用法詳解
這篇文章主要介紹了Javascript添加監(jiān)聽與刪除監(jiān)聽用法,較為詳細的分析了javascript原理與用法,并補充說明了事件監(jiān)聽的兼容性問題,非常具有實用價值,需要的朋友可以參考下2014-12-12
如何基于小程序?qū)崿F(xiàn)發(fā)送語音消息及轉(zhuǎn)文字功能
最近為小程序增加語音識別轉(zhuǎn)文字的功能,坑路不斷,特此記錄,下面這篇文章主要給大家介紹了關(guān)于如何基于小程序?qū)崿F(xiàn)發(fā)送語音消息及轉(zhuǎn)文字功能的相關(guān)資料,文中通過實例代碼介紹的非常詳細,需要的朋友可以參考下2022-11-11

