Next.js中间件:让页面代码变整洁的秘密武器

更新日期: 2025-10-29 阅读: 29 标签: 中间件

第一次听说Next.js中间件时,我心里想:"听起来不错,但真的有必要吗?"

现在我可以肯定地说:非常有必要。只要你做过用户权限验证、访问日志、A/B测试或者页面重定向中的任何一项,中间件就像是被低估的超强能力。

让我分享真正理解它价值的时刻,以及它如何把页面逻辑从混乱中拯救出来。


什么时候我真正体会到了它的好处?

那是在开发一个多角色应用时:管理员和普通用户需要不同的访问权限。每次用户访问受限制的页面,我不得不在页面或布局文件中加入:

  • 用户权限验证

  • 条件重定向逻辑

  • 访问记录

  • 偶尔还要做A/B测试

结果就是:代码变得臃肿,到处是重复的逻辑,if语句随处可见。换成中间件后,所有这些问题在一个文件中解决,入口统一了,页面代码也变得干净。


中间件到底是什么?

它在请求完成之前、在边缘运行你的代码,这是在react开始渲染之前就完成的。它像是一个轻量级的服务器功能。

中间件文件放在项目根目录,命名为middleware.ts(或者.js)。

看看这个基本例子:

// middleware.ts
import { NextResponse } from 'next/server'
import type { NextRequest } from 'next/server'

export function middleware(request: NextRequest) {
  const token = request.cookies.get('token')

  if (!token) {
    return NextResponse.redirect(new URL('/login', request.url))
  }
  return NextResponse.next()
}

// 配置哪些路由需要经过中间件
export const config = {
  matcher: ['/dashboard/:path*', '/settings/:path*'],
}

这个简单的中间件就能保护指定路由,不需要修改任何页面文件。


我实际使用的场景

  1. 用户验证和重定向

    • 未登录用户自动跳转到登录页

    • 已登录用户不能访问登录页面

  2. A/B测试

    • 根据请求头或Cookie显示不同版本

    • 保持用户始终看到同一个版本

  3. 多语言支持

    • 根据用户地区跳转到对应语言站点

    • 自动识别用户偏好语言

  4. 访问记录

    • 记录用户访问路径和来源

    • 统计会话信息

  5. 维护模式

    • 在特定时间段屏蔽某些页面

    • 显示维护提示页面

  6. 内部路由重写

    • 把外部URL映射到内部页面

    • 不改变浏览器地址栏的URL


路由匹配要精确

在middleware.ts中配置matcher,只对需要的页面生效,避免影响静态资源和公开页面。

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


快速上手三步走

  1. 创建middleware.ts文件

  2. 写一个简单的权限检查:验证Cookie或Session,未登录就重定向

  3. 配置matcher:只保护需要验证的路由

完成这些,打开浏览器看看,页面逻辑立刻变得清晰整洁。


实用技巧

读取请求信息:使用request.nextUrl、request.headers、request.cookies

重写而不是跳转:用NextResponse.rewrite可以无刷新更换内容

设置Header和Cookie:通过response.headers.set和response.cookies.set

保持A/B测试一致性:第一次分配后写入Cookie,后续请求保持相同版本

注意运行环境:边缘运行时没有Node.js内置模块,避免重量级计算,尽量在10毫秒内完成


什么时候用?什么时候不用?

适合使用:

  • 入口控制(权限、重定向、多语言、测试)

  • 简单的访问记录

  • 低延迟的路由重写

不适合使用:

  • 需要访问数据库的复杂业务逻辑

  • 这类需求更适合放在API路由或Server Actions中


为什么它如此有用?

页面代码更干净:把入口检查从组件中移走

跳转更快:在渲染前就决定页面去向

统一入口:所有入口规则在一个地方维护

不依赖额外服务:不需要自建后端服务器就能实现很多功能


完整示例:A/B测试 + 登录保护

// middleware.ts
import { NextResponse } from 'next/server'
import type { NextRequest } from 'next/server'

export function middleware(req: NextRequest) {
  const { nextUrl } = req
  const res = NextResponse.next()
  const token = req.cookies.get('token')?.value
  const isProtected = nextUrl.pathname.startsWith('/app')

  // 1. 登录保护
  if (isProtected && !token) {
    return NextResponse.redirect(new URL('/login', req.url))
  }

  // 2. A/B测试:如果没有Cookie就随机分配,然后设置Cookie保持一致性
  let bucket = req.cookies.get('ab-home')?.value
  if (!bucket) {
    bucket = Math.random() < 0.5 ? 'A' : 'B'
    res.cookies.set('ab-home', bucket, { path: '/', httpOnly: false })
  }

  // 3. 根据测试分组重写到不同页面
  if (nextUrl.pathname === '/' && bucket === 'B') {
    return NextResponse.rewrite(new URL('/home-b', req.url))
  }

  return res
}

export const config = {
  matcher: ['/', '/app/:path*'],
}


实际项目建议

从简单的需求开始,比如先实现登录保护。熟悉后再加入更复杂的功能。

注意错误处理,特别是在重定向时确保目标URL存在。

测试时要清除Cookie,确保中间件在各种情况下都能正常工作。

性能监控很重要,确保中间件不会成为瓶颈。


总结

把所有"入口需要做的事情"都集中到中间件中,页面和布局组件就能专注于内容展示。一个文件守护所有入口,这就是Next.js中间件的价值所在。

它让代码更易于维护,逻辑更清晰,开发效率更高。开始使用中间件,你会发现前端开发可以如此简洁高效。

本文内容仅供个人学习/研究/参考使用,不构成任何决策建议或专业指导。分享/转载时请标明原文来源,同时请勿将内容用于商业售卖、虚假宣传等非学习用途哦~感谢您的理解与支持!

链接: https://fly63.com/article/detial/13078

内容以共享、参考、研究为目的,不存在任何商业目的。其版权属原作者所有,如有侵权或违规,请与小编联系!情况属实本人将予以删除!