如何让Next.js的router.push()每次都经过中间件处理重定向?
问题解决:强制Next.js路由每次触发Middleware重定向
问题背景
使用Next.js客户端路由和middleware时,生产环境下router会缓存第一次的重定向结果,后续调用router.push('/')时直接跳转到缓存的目标路由,不再执行middleware逻辑。刷新浏览器后恢复正常,开发环境无此问题。需求是让router每次导航都进入middleware重新计算重定向目标。
复现步骤
- 多次从地址栏访问
/,由于middleware的随机逻辑,50%概率重定向到/dashboard,50%概率到/profile - 访问
/login,点击Login按钮触发router.push('/'),会被重定向到其中一个路由 - 点击Logout按钮回到
/login - 后续每次点击Login,都会跳转到和第一次相同的路由
问题原因
Next.js生产环境的客户端路由默认对重定向结果做缓存优化,当通过router.push访问曾经重定向过的路径时,会直接复用缓存的目标地址,跳过middleware重新执行。这是生产环境的性能优化策略,但会导致动态重定向逻辑失效。
解决方案
方案1:用router.replace替代router.push
router.replace不会向history栈添加新记录,同时会绕过Next.js的重定向缓存,强制触发middleware重新计算:
// 修改login.tsx中的登录逻辑 const login = () => { router.replace('/') }
方案2:添加随机查询参数绕过缓存
在跳转时给目标路径添加一个随机参数,让每次的路径“唯一”,避免缓存匹配:
// login.tsx const login = () => { router.push(`/?t=${Date.now()}`) }
同时在middleware中忽略这个随机参数,保证路径判断逻辑不受影响:
// middleware.ts export function middleware(request: NextRequest) { const url = request.nextUrl.clone() // 移除随机参数 url.searchParams.delete('t') if (url.pathname === '/') { if (Math.random() > 0.5) { return NextResponse.redirect(new URL('/dashboard', request.url)) } else { return NextResponse.redirect(new URL('/profile', request.url)) } } }
方案3:禁用全局重定向缓存(不推荐)
通过Next.js配置关闭全局重定向缓存,会影响所有路由的性能,仅作为兜底方案:
// next.config.js /** @type {import('next').NextConfig} */ const nextConfig = { experimental: { clientRouterFilter: false, }, } module.exports = nextConfig
验证效果
采用方案1或2后,每次点击Login按钮都会触发middleware重新执行随机重定向逻辑,不再复用之前的缓存结果。
内容的提问来源于stack exchange,提问作者Lautaro Riveiro
相关产品推荐
相关产品推荐

