第 7 章:中间件与 Edge Functions(进阶)
7.1 什么是 Middleware?
Middleware 是 Next.js 13+ 引入的一项功能,运行在请求开始阶段,可以在页面渲染之前对请求进行处理。
它的主要作用包括:
- 用户权限控制(如登录验证)
- 动态重定向或重写 URL
- 地域分发 / 语言选择
- 实现 A/B 测试逻辑
- 更高效的页面拦截(运行在边缘网络)
7.2 创建中间件文件
你只需要在项目根目录或 app/ 下创建一个名为 middleware.js(或 middleware.ts)的文件:
📄 middleware.js
import { NextResponse } from 'next/server';
export function middleware(request) {
const token = request.cookies.get('token')?.value;
if (!token && request.nextUrl.pathname.startsWith('/dashboard')) {
return NextResponse.redirect(new URL('/login', request.url));
}
return NextResponse.next(); // 继续后续流程
}
✅ 匹配路径:
- 自动应用于所有路由
- 可配合
matcher精确指定:
export const config = {
matcher: ['/dashboard/:path*', '/profile'],
};
7.3 中间件执行时机
中间件会在:
- 请求发送到页面或 API 路由 之前 执行
- 不会进入 React 组件内部
- 运行于 边缘网络(Edge) ,速度非常快
7.4 实现登录权限控制(案例)
需求: 用户访问 /admin 必须登录,否则重定向到 /login
📄 middleware.js
import { NextResponse } from 'next/server';
export function middleware(request) {
const isLoggedIn = request.cookies.get('auth')?.value === 'true';
const { pathname } = request.nextUrl;
if (pathname.startsWith('/admin') && !isLoggedIn) {
return NextResponse.redirect(new URL('/login', request.url));
}
return NextResponse.next();
}
export const config = {
matcher: ['/admin/:path*'],
};
📌 设置 cookie 示例(登录成功时):
// pages/api/login.js
export default function handler(req, res) {
res.setHeader('Set-Cookie', 'auth=true; Path=/; HttpOnly');
res.status(200).json({ message: '登录成功' });
}
7.5 URL 重写与重定向(高级用法)
✅ 重写(rewrite):改变路径但保持 URL 不变
export function middleware(request) {
const url = request.nextUrl.clone();
if (url.pathname === '/shop') {
url.pathname = '/store';
return NextResponse.rewrite(url);
}
return NextResponse.next();
}
✅ 重定向(redirect):跳转到新地址(URL 会变化)
export function middleware(request) {
const url = request.nextUrl.clone();
if (url.pathname === '/old-page') {
url.pathname = '/new-page';
return NextResponse.redirect(url);
}
return NextResponse.next();
}
7.6 Edge Functions 与 Middleware 的区别
| 功能 | Middleware | Edge Functions |
|---|---|---|
| 运行时机 | 请求前 | 自定义 API 路由 |
| 文件位置 | middleware.js | pages/api/xxx/route.js |
| 使用场景 | 权限控制、重写、A/B 测试 | 定制化请求处理(更复杂逻辑) |
| 执行位置 | Vercel 边缘节点(全球 CDN) | 同样支持 Edge |
7.7 示例:A/B 测试
export function middleware(request) {
const random = Math.random();
const url = request.nextUrl.clone();
if (request.nextUrl.pathname === '/') {
url.pathname = random > 0.5 ? '/version-a' : '/version-b';
return NextResponse.rewrite(url);
}
return NextResponse.next();
}
7.8 常见限制与注意事项
| 限制项 | 说明 |
|---|---|
| 不能访问 React 组件 | middleware 是运行在服务端、请求前 |
不支持 fetch() 请求外部数据(需 Edge) | 必须在 1ms 内返回响应 |
| 不支持 Node.js 原生模块 | 运行环境不是 Node,而是 Edge Runtime |
| cookie 访问为只读 | 想修改 cookie 应在 API 路由中完成 |
✅ 小结
| 功能 | 方法 |
|---|---|
| 权限控制 | 判断 cookie,拦截请求重定向 |
| URL 重写 | 使用 NextResponse.rewrite() |
| 路由跳转 | 使用 NextResponse.redirect() |
| 匹配规则 | 使用 config.matcher 配置作用路径 |
| 执行位置 | 运行在边缘网络,快且轻量 |
| 实现 A/B 测试 | 随机决定路径重写方向 |