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

Next.js App Router:将所有路由重定向至嵌套动态根路由

多店铺电商路由重定向最佳实现方案(Next.js App Router)

核心方案:使用 Middleware

这是适配你场景的最优解——Middleware能在请求到达页面之前全局拦截所有路由请求,动态处理Cookie判断和重定向逻辑,既高效又无需在每个页面重复写代码,完美覆盖所有路由重定向需求。

具体实现步骤

1. 创建 Middleware 文件

在项目根目录新建 middleware.ts(或 .js),Next.js 会自动识别并启用这个文件的全局拦截逻辑。

2. 编写 Middleware 核心逻辑

import { NextResponse } from 'next/server'
import type { NextRequest } from 'next/server'

export function middleware(request: NextRequest) {
  // 排除无需重定向的路径:店铺选择页、静态资源、API路由等
  const excludedPaths = ['/select-store', '/_next', '/api', '/favicon.ico']
  if (excludedPaths.some(path => request.nextUrl.pathname.startsWith(path))) {
    return NextResponse.next()
  }

  // 从Cookie读取已选店铺ID和购物模式
  const storeId = request.cookies.get('storeId')?.value
  const shoppingMode = request.cookies.get('shoppingMode')?.value

  // 情况1:已保存店铺和模式信息
  if (storeId && shoppingMode) {
    const targetPath = `/store/${storeId}/sm/${shoppingMode}${request.nextUrl.pathname}`
    // 避免重复重定向(已在嵌套路由内的请求直接放行)
    if (!request.nextUrl.pathname.startsWith(`/store/${storeId}/sm/${shoppingMode}`)) {
      return NextResponse.redirect(new URL(targetPath, request.url))
    }
    return NextResponse.next()
  }

  // 情况2:未选择店铺,重定向到选择页并携带当前路径作为跳转参数
  const redirectUrl = new URL('/select-store', request.url)
  redirectUrl.searchParams.set('redirect', encodeURIComponent(request.nextUrl.pathname))
  return NextResponse.redirect(redirectUrl)
}

// 指定Middleware生效的路由范围(匹配所有路由)
export const config = {
  matcher: '/:path*',
}

3. 实现店铺选择页面

创建 app/select-store/page.tsx,处理用户选择逻辑,设置Cookie后跳转到目标路由:

'use client'

import { useRouter, useSearchParams } from 'next/navigation'
import { useState } from 'react'

export default function SelectStorePage() {
  const router = useRouter()
  const searchParams = useSearchParams()
  const redirectPath = searchParams.get('redirect') || '/'
  const [storeId, setStoreId] = useState('')
  const [shoppingMode, setShoppingMode] = useState('pickup')

  const handleSubmit = (e: React.FormEvent) => {
    e.preventDefault()
    if (!storeId) return

    // 设置Cookie(有效期可按需调整)
    document.cookie = `storeId=${storeId}; path=/; max-age=86400`
    document.cookie = `shoppingMode=${shoppingMode}; path=/; max-age=86400`

    // 跳转到目标路由
    router.push(`/store/${storeId}/sm/${shoppingMode}${redirectPath}`)
  }

  return (
    <div>
      <h2>选择店铺和购物模式</h2>
      <form onSubmit={handleSubmit}>
        <div>
          <label>店铺ID:</label>
          <input
            type="text"
            value={storeId}
            onChange={(e) => setStoreId(e.target.value)}
            required
          />
        </div>
        <div>
          <label>购物模式:</label>
          <select
            value={shoppingMode}
            onChange={(e) => setShoppingMode(e.target.value)}
          >
            <option value="pickup">自提</option>
            <option value="delivery">配送</option>
          </select>
        </div>
        <button type="submit">确认选择</button>
      </form>
    </div>
  )
}

其他方案的局限性

  • 配置文件重定向:next.config.js 里的重定向只能是静态规则,无法动态读取用户Cookie中的店铺ID和模式,完全不适用你的动态场景。
  • 页面内重定向:需要在每个页面组件中写重定向逻辑,代码冗余,且会出现页面闪烁(页面开始渲染后才触发重定向),用户体验差。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.04 01:23:36