Next.js 路由与中间件

1. 什么是中间件?

中间件是一个函数 ,它运行在服务器端,位于请求响应之间。当一个请求进入你的 Next.js 应用时,它会首先经过中间件,然后才会继续到对应的页面路由。

核心作用

  • 认证与授权:检查用户是否已登录,重定向未登录用户。
  • 地理位置定位:根据用户的 IP 地址重定向到特定语言或地区的页面。
  • A/B 测试:将用户随机分配到不同版本的页面。
  • 日志与分析:记录请求信息,用于分析用户行为。
  • 机器人检测与防火墙:阻止恶意请求。

2. 如何创建中间件

创建中间件非常简单,只需要在你的项目根目录下创建一个名为 middleware.ts (或 .js) 的文件。 文件位置

lua 复制代码
.
├── src/
│   ├── app/
│   │   └── page.tsx
│   └── middleware.ts  <-- 在这里创建
├── package.json
└── ...

或者 ,如果你没有使用 src 目录:

lua 复制代码
.
├── app/
│   └── page.tsx
├── middleware.ts  <-- 在这里创建
├── package.json
└── ...

3. 中间件的核心:matcher 配置

默认情况下,中间件会匹配所有路径 (除了 _next/static, _next/image, api 等内部路径)。但这通常不是我们想要的,我们只想让中间件作用于特定的路由。 这时就需要 matcher 配置。它是一个数组,定义了哪些路径会触发中间件。

typescript 复制代码
// middleware.ts
import { NextResponse } from 'next/server';
import type { NextRequest } from 'next/server';
export function middleware(request: NextRequest) {
  // 中间件逻辑...
}
// matcher 配置
export const config = {
  matcher: [
    /*
     * 匹配所有路径路径,除了以这些开头的:
     * - api (API routes)
     * - _next/static (static files)
     * - _next/image (image optimization files)
     * - favicon.ico (favicon file)
     */
    '/((?!api|_next/static|_next/image|favicon.ico).*)',
  ],
};

matcher 的高级用法

  • 通配符

    • /about/:path*:匹配 /about/ 及其所有子路径,如 /about/team
  • 数组 :可以指定多个路径。

    typescript 复制代码
    matcher: ['/dashboard/:path*', '/profile', '/settings']
  • 否定断言 (?!...):上面的例子中,(?!api|_next/static|...) 是一个正则表达式的否定断言,意思是"不匹配以 api_next/static... 开头的路径"。这是最常用和推荐的模式,可以避免中间件影响静态资源和 API。


4. 实战示例

让我们通过几个常见例子来理解如何编写中间件逻辑。

示例 1:认证保护

目标 :保护 /dashboard 下的所有页面,如果用户未登录(没有 token),则重定向到登录页。

typescript 复制代码
// middleware.ts
import { NextResponse } from 'next/server';
import type { NextRequest } from 'next/server';
export function middleware(request: NextRequest) {
  // 1. 检查请求路径是否包含 /dashboard
  if (request.nextUrl.pathname.startsWith('/dashboard')) {
    // 2. 从 cookies 中获取 token
    const token = request.cookies.get('auth_token')?.value;
    // 3. 如果没有 token,重定向到登录页
    if (!token) {
      // new URL('目标路径', '基础路径') 是创建重定向 URL 的安全方法
      const loginUrl = new URL('/login', request.url);
      return NextResponse.redirect(loginUrl);
    }
  }
  // 4. 如果已登录或不访问 /dashboard,则正常放行
  return NextResponse.next();
}
// 只对 /dashboard 及其子路径生效
export const config = {
  matcher: ['/dashboard/:path*'],
};

示例 2:国际化重定向

目标 :根据用户的 Accept-Language 头部信息,将他们重定向到对应的语言页面(如 /en-US//fr/)。

typescript 复制代码
// middleware.ts
import { NextResponse } from 'next/server';
import type { NextRequest } from 'next/server';
export function middleware(request: NextRequest) {
  // 检查路径中是否已经有语言前缀
  const pathname = request.nextUrl.pathname;
  if (pathname.startsWith('/en-US') || pathname.startsWith('/fr')) {
    return NextResponse.next();
  }
  // 获取 Accept-Language 头部
  const acceptLanguage = request.headers.get('accept-language');
  let locale = 'en-US'; // 默认语言
  if (acceptLanguage) {
    // 简单解析,实际项目中可能需要更复杂的逻辑
    if (acceptLanguage.includes('fr')) {
      locale = 'fr';
    }
  }
  // 重定向到带语言前缀的首页
  const localeUrl = new URL(`/${locale}${pathname}`, request.url);
  return NextResponse.redirect(localeUrl);
}
// 匹配所有路径,但排除内部路径
export const config = {
  matcher: [
    '/((?!_next|api|favicon.ico).*)',
  ],
};

5. 中间件 API 详解

middleware 函数中,你主要会用到两个对象:

NextRequest 对象

它扩展了标准的 Request API,提供了一些便捷属性:

  • request.nextUrl:一个扩展了 URL 的对象,包含了路由信息。
  • request.cookies:方便地读写 cookies。
  • request.geo:获取请求的地理位置信息(国家、地区、城市等)。

NextResponse 对象

它扩展了标准的 Response API,用于生成响应:

  • NextResponse.next():继续处理请求,进入路由链。
  • NextResponse.redirect(url):重定向到指定的 URL。
  • NextResponse.rewrite(url)重写 URL。这是非常强大的功能,它会在服务器端"静默"地将请求 /old-page 映射到 /new-page,但用户浏览器地址栏的 URL 仍然显示为 /old-page
  • NextResponse.json():发送 JSON 响应。

6. 路由配置(App Router)

在 Next.js 的 App Router 中,路由配置主要是基于文件系统约定的,而不是一个中央配置文件。

  • 动态路由app/blog/[slug]/page.tsx -> /blog/hello-world
  • 路由组app/(marketing)/about/page.tsx -> /about (括号不影响 URL)
  • 并行路由app/@analytics/page.tsx -> 在 layout.tsx 中渲染
  • 拦截路由app/(.)photo/[id]/page.tsx -> 可以拦截 /photo/123 并在模态框中显示 中间件 (middleware.ts) 是这个文件系统路由之上的全局或条件性逻辑层 。它不直接定义路由,而是影响路由的行为(重定向、重写、认证等)。

总结

特性 描述
文件 middleware.ts (或 .js)
位置 项目根目录或 src/ 目录
核心功能 在页面渲染前执行服务器端代码
关键配置 matcher 数组,用于定义中间件匹配的路径
主要用途 认证、重定向、A/B 测试、国际化、日志
核心 API NextRequest (请求信息), NextResponse (响应控制)
与路由关系 是文件系统路由之上的逻辑增强层
相关推荐
前端婴幼儿1 小时前
前端直接下载到本地(实时显示下载进度)
前端
三小河1 小时前
前端 Class 语法从 0 开始学起
前端
hjt_未来可期1 小时前
js实现复制、粘贴文字
前端·javascript·html
小明记账簿_微信小程序1 小时前
webpack实用配置dev--react(一)
前端
videring1 小时前
打字机效果-支持ckeditor5、框架无关
前端·javascript
ohyeah1 小时前
AI First 时代:用大模型构建轻量级后台管理系统
前端·llm
Apeng_09191 小时前
vue实现页面不断插入内容并且自动滚动功能
前端·javascript·vue.js
孟祥_成都2 小时前
Prompt 还能哄女朋友!你真的知道如何问 ai 问题吗?
前端·人工智能
前端涂涂2 小时前
第3讲:BTC-数据结构
前端