You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

项目根目录Middleware下Shallow路由跳转失效问题求助

Shallow路由导航失效:地址栏变更但页面未更新

问题现象

在Next.js项目中使用shallow选项导航时,浏览器地址栏链接已变更,但页面内容未更新。涉及场景:

  • 侧边栏通过NextLink添加shallow属性导航
  • 按钮点击调用router.push并配置shallow: true导航

相关代码

NextLink导航代码

<NextLink href='/dashboard' passHref shallow>Dashboard</NextLink>
<NextLink href='/users' passHref shallow>Users</NextLink>
<NextLink href='/users' passHref shallow>Posts</NextLink>

router.push导航代码

<Button onClick={() => router.push('/dashboard', {}, { shallow: true })}>Dashboard</Button>

Middleware代码(./src/middleware.ts)

import { NextResponse, NextMiddleware } from 'next/server';

const PUBLIC_FILE = /\.(.*)$/;
export const middleware: NextMiddleware = (req) => {
  const acceptLanguage =
    req?.headers?.get('accept-language') &&
    req?.headers?.get('accept-language')?.slice(0, 2);

  if (
    req.nextUrl.pathname.startsWith('/_next') ||
    req.nextUrl.pathname.includes('/api/') ||
    PUBLIC_FILE.test(req.nextUrl.pathname)
  ) {
    return;
  }

  if (req.nextUrl.locale === 'default') {
    const newUrl = req.nextUrl.clone();
    
    newUrl.locale = acceptLanguage || 'en';
    
    return NextResponse.redirect(newUrl);
  }
};

依赖版本

  • "next": "^12.3.4"
  • "next-translate": "^2.0.4"
  • "react": "^17.0.2"
  • "react-dom": "^17.0.2"

原因分析

  1. Shallow路由适用场景误解:Next.js的shallow路由仅支持同一页面路由下的查询参数/哈希变更(如/dashboard?tab=1 → /dashboard?tab=2)。若跳转到不同路由路径(如/dashboard → /users),shallow选项完全无效,因为这属于跨页面路由切换,必须触发完整导航流程。
  2. Middleware重定向打破客户端导航:即使是符合shallow场景的同路由导航,当前Middleware会对默认locale路径触发服务器端重定向。而shallow路由依赖纯客户端导航,一旦触发服务器端重定向,客户端shallow逻辑会被中断,导致页面无法正常更新。

解决方案

1. 修正Shallow路由的使用

若跳转到不同路由路径,直接移除shallow属性(对跨路由导航无效):

<NextLink href='/dashboard' passHref>Dashboard</NextLink>
<NextLink href='/users' passHref>Users</NextLink>
<NextLink href='/users' passHref>Posts</NextLink>

2. 修改Middleware避免中断客户端导航

在Middleware中判断是否为客户端发起的导航(通过x-nextjs-data请求头),若是则跳过重定向逻辑,保留shallow路由的客户端行为:

import { NextResponse, NextMiddleware } from 'next/server';

const PUBLIC_FILE = /\.(.*)$/;
export const middleware: NextMiddleware = (req) => {
  const acceptLanguage = req?.headers?.get('accept-language')?.slice(0, 2);

  if (
    req.nextUrl.pathname.startsWith('/_next') ||
    req.nextUrl.pathname.includes('/api/') ||
    PUBLIC_FILE.test(req.nextUrl.pathname)
  ) {
    return;
  }

  // 判断是否为客户端导航(Next.js客户端导航会携带x-nextjs-data头)
  const isClientNavigation = req.headers.get('x-nextjs-data') !== null;

  if (req.nextUrl.locale === 'default') {
    // 客户端导航时跳过重定向,保留shallow路由行为
    if (isClientNavigation) {
      return NextResponse.next();
    }

    const newUrl = req.nextUrl.clone();
    newUrl.locale = acceptLanguage || 'en';
    return NextResponse.redirect(newUrl);
  }
};

内容的提问来源于stack exchange,提问作者IncognitoUser

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.23 21:12:07