找回密码
立即注册
搜索
热搜: Java Python Linux Go
发回帖 发新帖

4648

积分

0

好友

606

主题
发表于 2 小时前 | 查看: 2| 回复: 0

当初第一次听说 Next.js Middleware,我心想:“挺酷,但我真的需要吗?”

结论:需要。只要你做 鉴权、日志、A/B 测试、重定向 里的任意一件,它就像 被低估的超能力

下面是我“开窍”的瞬间、现在的用法,以及它为什么能把页面逻辑从泥沼里救出来。

什么时候我真的懂了它?

多角色应用:管理员 vs 普通用户。每次用户访问受限页,我都要在页面/布局里塞:

  • 鉴权
  • 条件重定向
  • 埋点
  • 偶尔 A/B 测试

结果:臃肿、重复、到处是 if。换上 middleware 后:一个文件、一个层,入口统一、页面干净。

Middleware 到底干啥?

在请求完成前、在边缘(Edge)就运行你的代码——在 React 渲染之前先把路清掉。

它放在项目根目录 /middleware.ts(或 .js),像轻量 serverless。

// 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*'], // 只对这些路由生效
}

小更正:路由匹配 matcher 应该导出在 middleware.ts 中的 config,而不是 next.config.js

这段小小的中间件就能 保护指定路由,不用改任意一个页面文件。

我真正在用的场景

用途 带来的好处
🔐 鉴权重定向 未登录直送 /login,已登录拦截访问 /login
🧪 A/B 测试 基于 Header/Cookie 切不同布局或实验
🌍 地域/语言路由 按地区/语言跳转到对应站点或路径
📈 轻量埋点 记录路径、来源、Session 等入口信息
🚧 维护模式 时间窗内屏蔽部分路由或返回占位页
🔁 Rewrites NextResponse.rewrite 映射到内部页面或 Edge API

路由匹配像忍者一样精准

把匹配写进 middleware.tsconfig.matcher,只对需要的页面生效,避免对静态资源、公开页加负担。

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

三步上手(今天就能用)

  1. 创建 middleware.ts
  2. 写一个简单鉴权:检查 Cookie/Session,未登录重定向
  3. 加上 config.matcher:只匹配需要保护/改写的路由
  4. 打开浏览器,看页面逻辑 瞬间变干净 🎉

进阶小技巧

  • 读取请求信息request.nextUrlrequest.headersrequest.cookies
  • 改写而非跳转NextResponse.rewrite(new URL('/internal', request.url)) 无刷新换内容
  • 追加 Header/Cookieresponse.headers.set(...)response.cookies.set(...)
  • A/B 实验粘性:首次分流后 写入 Cookie,后续请求保持一致
  • 边缘运行注意:Edge Runtime 没有 Node 内置模块,尽量 少做重 CPU 计算,<10ms 收工

什么时候用 Middleware,什么时候别用?

  • 该用:入口控制(鉴权/重定向/国际化/实验)、轻量埋点、低延迟改写
  • 别用:需要访问数据库做复杂业务;这类逻辑放 Route Handler / Server Actions / API 更合适

为什么它像“超能力”

  • 页面更干净:把“进门检查”从组件里搬走
  • 更快的跳转渲染前 就决定去向
  • 入口集中化:所有入口规则 一处维护
  • 不依赖自建后端:没有自定义服务器也能搞定一堆事

一个实用范例(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*'],
}

把“进门要做的事” 收口到 Middleware,页面和布局变得 专注又轻盈一个文件,守住所有入口——这就是 Next.js Middleware 的爽点。

如果你也在做类似的 Next.js 项目,欢迎来云栈社区一起交流。




上一篇:7个开发者最容易犯的数据泄露错误:API响应、日志与前端密钥
下一篇:Claude Code 多 Agent 软件工厂:如何让功能在你睡觉时自动交付
您需要登录后才可以回帖 登录 | 立即注册

手机版|小黑屋|网站地图|云栈社区 ( 苏ICP备2022046150号-2 )

GMT+8, 2026-8-17 04:59 , Processed in 0.878107 second(s), 41 queries , Gzip On.

Powered by Discuz! X3.5

© 2025-2026 云栈社区.

快速回复 返回顶部 返回列表