routing-middleware
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseVercel Routing Middleware
Vercel Routing Middleware
You are an expert in Vercel Routing Middleware — the platform-level request interception layer.
您是 Vercel Routing Middleware 的专家——这是平台级别的请求拦截层。
What It Is
什么是 Vercel Routing Middleware
Routing Middleware runs before the cache on every request matching its config. It is a Vercel platform feature (not framework-specific) that works with Next.js, SvelteKit, Astro, Nuxt, or any deployed framework. Built on Fluid Compute.
- File: or
middleware.tsat the project rootmiddleware.js - Default export required (function name can be anything)
- Runtimes: Edge (default), Node.js (), Bun (Node.js +
runtime: 'nodejs'in vercel.json)bunVersion
Routing Middleware 会在缓存之前,对所有匹配其配置的请求运行。它是一项Vercel 平台功能(不绑定特定框架),可与 Next.js、SvelteKit、Astro、Nuxt 或任何已部署的框架配合使用,基于 Fluid Compute 构建。
- 文件位置:项目根目录下的 或
middleware.tsmiddleware.js - 必须默认导出(函数名称可自定义)
- 支持的运行时:Edge(默认)、Node.js(需配置 )、Bun(基于 Node.js 配置,需在 vercel.json 中指定
runtime: 'nodejs')bunVersion
CRITICAL: Middleware Disambiguation
关键说明:Middleware 概念区分
There are THREE "middleware" concepts in the Vercel ecosystem:
| Concept | File | Runtime | Scope | When to Use |
|---|---|---|---|---|
| Vercel Routing Middleware | | Edge/Node/Bun | Any framework, platform-level | Request interception before cache: rewrites, redirects, geo, A/B |
| Next.js 16 Proxy | | Node.js only | Next.js 16+ only | Network-boundary proxy needing full Node APIs. NOT for auth. |
| Edge Functions | Any function file | V8 isolates | General-purpose | Standalone edge compute endpoints, not an interception layer |
Why the rename in Next.js 16: → clarifies it sits at the network boundary (not general-purpose middleware). Partly motivated by CVE-2025-29927 (middleware auth bypass via header). The exported function must also be renamed from to . Migration codemod:
middleware.tsproxy.tsx-middleware-subrequestmiddlewareproxynpx @next/codemod@latest middleware-to-proxyDeprecation: Next.js 16 still accepts but treats it as deprecated and logs a warning. It will be removed in a future version.
middleware.tsVercel 生态中有三种“middleware”概念:
| 概念 | 文件 | 运行时 | 适用范围 | 使用场景 |
|---|---|---|---|---|
| Vercel Routing Middleware | 根目录下的 | Edge/Node/Bun | 任意框架,平台级别 | 缓存前的请求拦截:重写、重定向、地域适配、A/B 测试 |
| Next.js 16 Proxy | 根目录(或使用 | 仅支持 Node.js | 仅 Next.js 16+ | 需要完整 Node API 的网络边界代理。不用于认证。 |
| Edge Functions | 任意函数文件 | V8 隔离环境 | 通用场景 | 独立的边缘计算端点,非请求拦截层 |
Next.js 16 重命名原因: 改为 是为了明确其位于网络边界(而非通用 middleware)。部分原因是受 CVE-2025-29927 漏洞(通过 头绕过 middleware 认证)的影响。导出函数也必须从 重命名为 。迁移代码修改工具:
middleware.tsproxy.tsx-middleware-subrequestmiddlewareproxynpx @next/codemod@latest middleware-to-proxy弃用说明:Next.js 16 仍接受 ,但会将其标记为已弃用并记录警告,未来版本将移除该支持。
middleware.tsBun Runtime
Bun 运行时配置
To run Routing Middleware (and all Vercel Functions) on Bun, add to :
bunVersionvercel.jsonjson
{
"bunVersion": "1.x"
}Set the middleware runtime to — Bun replaces the Node.js runtime transparently:
nodejsts
export const config = {
runtime: 'nodejs', // Bun swaps in when bunVersion is set
};Bun reduces average latency by ~28% in CPU-bound workloads. Currently in Public Beta — supports Next.js, Express, Hono, and Nitro.
要在 Bun 上运行 Routing Middleware(及所有 Vercel Functions),需在 中添加 :
vercel.jsonbunVersionjson
{
"bunVersion": "1.x"
}将 middleware 运行时设置为 ——Bun 会自动替换 Node.js 运行时:
nodejsts
export const config = {
runtime: 'nodejs', // 当配置 bunVersion 后,Bun 会自动替换
};在 CPU 密集型工作负载中,Bun 可将平均延迟降低约 28%。目前处于公开测试阶段——支持 Next.js、Express、Hono 和 Nitro。
Basic Example
基础示例
ts
// middleware.ts (project root)
import { geolocation, rewrite } from '@vercel/functions';
export default function middleware(request: Request) {
const { country } = geolocation(request);
const url = new URL(request.url);
url.pathname = country === 'US' ? '/us' + url.pathname : '/intl' + url.pathname;
return rewrite(url);
}
export const config = {
runtime: 'edge', // 'edge' (default) | 'nodejs'
};ts
// middleware.ts(项目根目录)
import { geolocation, rewrite } from '@vercel/functions';
export default function middleware(request: Request) {
const { country } = geolocation(request);
const url = new URL(request.url);
url.pathname = country === 'US' ? '/us' + url.pathname : '/intl' + url.pathname;
return rewrite(url);
}
export const config = {
runtime: 'edge', // 'edge'(默认)| 'nodejs'
};Helper Methods (@vercel/functions
)
@vercel/functions辅助方法(@vercel/functions
)
@vercel/functionsFor non-Next.js frameworks, import from :
@vercel/functions| Helper | Purpose |
|---|---|
| Continue middleware chain (optionally modify headers) |
| Transparently serve content from a different URL |
| Get |
| Get client IP address |
| Keep function running after response is sent |
For Next.js, equivalent helpers are on (, , ) and (, ).
NextResponsenext()rewrite()redirect()NextRequestrequest.georequest.ip对于非 Next.js 框架,可从 导入以下方法:
@vercel/functions| 辅助方法 | 用途 |
|---|---|
| 继续 middleware 链(可选择性修改请求头) |
| 透明地从其他 URL 提供内容 |
| 获取 |
| 获取客户端 IP 地址 |
| 在响应发送后保持函数运行 |
对于 Next.js,等效的辅助方法位于 (、、)和 (、)上。
NextResponsenext()rewrite()redirect()NextRequestrequest.georequest.ipMatcher Configuration
匹配规则配置
Middleware runs on every route by default. Use to scope it:
config.matcherts
// Single path
export const config = { matcher: '/dashboard/:path*' };
// Multiple paths
export const config = { matcher: ['/dashboard/:path*', '/api/:path*'] };
// Regex: exclude static files
export const config = {
matcher: ['/((?!_next/static|favicon.ico).*)'],
};Tip: Using is preferred — unmatched paths skip middleware invocation entirely (saves compute).
matcher默认情况下,Middleware 会在所有路由上运行。可使用 来限定其作用范围:
config.matcherts
// 单个路径
export const config = { matcher: '/dashboard/:path*' };
// 多个路径
export const config = { matcher: ['/dashboard/:path*', '/api/:path*'] };
// 正则表达式:排除静态文件
export const config = {
matcher: ['/((?!_next/static|favicon.ico).*)'],
};提示:推荐使用 ——不匹配的路径会完全跳过 middleware 调用(节省计算资源)。
matcherCommon Patterns
常见使用模式
IP-Based Header Injection
基于 IP 的请求头注入
ts
import { ipAddress, next } from '@vercel/functions';
export default function middleware(request: Request) {
return next({ headers: { 'x-real-ip': ipAddress(request) || 'unknown' } });
}ts
import { ipAddress, next } from '@vercel/functions';
export default function middleware(request: Request) {
return next({ headers: { 'x-real-ip': ipAddress(request) || 'unknown' } });
}A/B Testing via Edge Config
借助 Edge Config 实现 A/B 测试
ts
import { get } from '@vercel/edge-config';
import { rewrite } from '@vercel/functions';
export default async function middleware(request: Request) {
const variant = await get('experiment-homepage'); // <1ms read
const url = new URL(request.url);
url.pathname = variant === 'B' ? '/home-b' : '/home-a';
return rewrite(url);
}ts
import { get } from '@vercel/edge-config';
import { rewrite } from '@vercel/functions';
export default async function middleware(request: Request) {
const variant = await get('experiment-homepage'); // 读取耗时 <1ms
const url = new URL(request.url);
url.pathname = variant === 'B' ? '/home-b' : '/home-a';
return rewrite(url);
}Background Processing
后台处理
ts
import type { RequestContext } from '@vercel/functions';
export default function middleware(request: Request, context: RequestContext) {
context.waitUntil(
fetch('https://analytics.example.com/log', { method: 'POST', body: request.url })
);
return new Response('OK');
}ts
import type { RequestContext } from '@vercel/functions';
export default function middleware(request: Request, context: RequestContext) {
context.waitUntil(
fetch('https://analytics.example.com/log', { method: 'POST', body: request.url })
);
return new Response('OK');
}Request Limits
请求限制
| Limit | Value |
|---|---|
| Max URL length | 14 KB |
| Max request body | 4 MB |
| Max request headers | 64 headers / 16 KB total |
| 限制项 | 数值 |
|---|---|
| 最大 URL 长度 | 14 KB |
| 最大请求体大小 | 4 MB |
| 最大请求头数量 | 64 个请求头 / 总大小 16 KB |
Three CDN Routing Mechanisms
三种 CDN 路由机制
Vercel's CDN supports three routing mechanisms, evaluated in this order:
| Order | Mechanism | Scope | Deploy Required | How to Configure |
|---|---|---|---|---|
| 1 | Bulk Redirects | Up to 1M static path→path redirects | No (runtime via Dashboard/API/CLI) | Dashboard, CSV upload, REST API |
| 2 | Project-Level Routes | Headers, rewrites, redirects | No (instant publish) | Dashboard, API, CLI, Vercel SDK |
| 3 | Deployment Config Routes | Full routing rules | Yes (deploy) | |
Project-level routes (added March 2026) let you update routing rules — response headers, rewrites to external APIs — without triggering a new deployment. They run after bulk redirects and before deployment config routes. Available on all plans.
Vercel CDN 支持三种路由机制,按以下顺序执行:
| 顺序 | 机制 | 适用范围 | 是否需要部署 | 配置方式 |
|---|---|---|---|---|
| 1 | 批量重定向 | 最多 100 万条静态路径→路径重定向 | 无需部署(通过控制台/API/CLI 实时生效) | 控制台、CSV 上传、REST API |
| 2 | 项目级路由 | 请求头、重写、重定向 | 无需部署(即时发布) | 控制台、API、CLI、Vercel SDK |
| 3 | 部署配置路由 | 完整路由规则 | 需要部署 | |
项目级路由(2026 年 3 月推出)允许您更新路由规则——响应头、外部 API 重写——无需触发新部署。它在批量重定向之后、部署配置路由之前运行,所有套餐均支持。
Project-Level Routes — Configuration Methods
项目级路由——配置方式
Project-level routes take effect instantly (no deploy required). Four ways to manage them:
| Method | How |
|---|---|
| Dashboard | Project → CDN → Routing tab. Live map of global traffic, cache management, and route editor in one view. |
| REST API | |
| Vercel CLI | Managed via |
| Vercel SDK | |
Use project-level routes for operational changes (CORS headers, API proxy rewrites, A/B redirects) that shouldn't require a full redeploy.
项目级路由即时生效(无需部署),有四种管理方式:
| 方式 | 操作说明 |
|---|---|
| 控制台 | 项目 → CDN → 路由标签页。可查看全球流量实时地图、缓存管理和路由编辑器。 |
| REST API | |
| Vercel CLI | 通过 |
| Vercel SDK | |
项目级路由适用于无需完整重新部署的运维变更(CORS 头、API 代理重写、A/B 测试重定向)。
Programmatic Configuration with vercel.ts
vercel.ts使用 vercel.ts
进行程序化配置
vercel.tsInstead of static , you can use (or , , , ) with the package for type-safe, dynamic routing configuration:
vercel.jsonvercel.ts.js.mjs.cjs.mts@vercel/configts
// vercel.ts
import { defineConfig } from '@vercel/config';
export default defineConfig({
rewrites: [
{ source: '/api/:path*', destination: 'https://backend.example.com/:path*' },
],
headers: [
{ source: '/(.*)', headers: [{ key: 'X-Frame-Options', value: 'DENY' }] },
],
});CLI commands:
- — compile to JSON (stdout)
npx @vercel/config compile - — validate and show summary
npx @vercel/config validate - — generate
npx @vercel/config generatelocally for developmentvercel.json
Constraint: Only one config file per project — or , not both.
vercel.jsonvercel.ts除了静态的 ,您还可以使用 (或 、、、)配合 包,实现类型安全的动态路由配置:
vercel.jsonvercel.ts.js.mjs.cjs.mts@vercel/configts
// vercel.ts
import { defineConfig } from '@vercel/config';
export default defineConfig({
rewrites: [
{ source: '/api/:path*', destination: 'https://backend.example.com/:path*' },
],
headers: [
{ source: '/(.*)', headers: [{ key: 'X-Frame-Options', value: 'DENY' }] },
],
});CLI 命令:
- ——编译为 JSON 格式(输出到标准输出)
npx @vercel/config compile - ——验证配置并显示摘要
npx @vercel/config validate - ——在本地生成
npx @vercel/config generate用于开发vercel.json
约束:每个项目仅能使用一个配置文件—— 或 ,不可同时使用。
vercel.jsonvercel.tsWhen to Use
适用场景
- Geo-personalization of static pages (runs before cache)
- A/B testing rewrites with Edge Config
- Custom redirects based on request properties
- Header injection (CSP, CORS, custom headers)
- Lightweight auth checks (defense-in-depth only — not sole auth layer)
- Project-level routes for headers/rewrites without redeploying
- 静态页面的地域个性化处理(在缓存前运行)
- 借助 Edge Config 实现 A/B 测试重写
- 基于请求属性的自定义重定向
- 请求头注入(CSP、CORS、自定义请求头)
- 轻量级认证检查(仅作为纵深防御——不可作为唯一认证层)
- 使用项目级路由配置请求头/重写,无需重新部署
When NOT to Use
不适用场景
- Need full Node.js APIs in Next.js → use
proxy.ts - General compute at the edge → use Edge Functions
- Heavy business logic or database queries → use server-side framework features
- Auth as sole protection → use Layouts, Server Components, or Route Handlers
- Thousands of static redirects → use Bulk Redirects (up to 1M per project)
- Next.js 中需要完整 Node.js API → 使用
proxy.ts - 通用边缘计算 → 使用 Edge Functions
- 复杂业务逻辑或数据库查询 → 使用服务端框架特性
- 认证作为唯一保护机制 → 使用布局组件、服务端组件或路由处理器
- 数千条静态重定向 → 使用批量重定向(每个项目最多支持 100 万条)
References
参考资料
- 📖 docs: https://vercel.com/docs/routing-middleware
- 📖 API reference: https://vercel.com/docs/routing-middleware/api
- 📖 getting started: https://vercel.com/docs/routing-middleware/getting-started