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

Next.js 14 App Router如何实现301重定向?

问题

我的项目里产品的slug支持动态更新,当slug更新后,我希望旧slug的页面能以301永久重定向跳转到新slug页面,但目前只能实现308重定向。我已经尝试过以下两种方案,都没达到预期:

  1. 在Page组件中使用permanentRedirect:
export default async function Page({ params: { slug } }: Props) {
  const productData: Promise<Product> = getProduct(slug);

  const product = await productData;

  if (product.slug !== slug) {
    // redirect to the correct slug
    permanentRedirect(`/product/${product.slug}`);
  }
  // 其他页面逻辑
}
  1. 在next.config.js中配置静态redirects:
async redirects() {
  return [
    {
      source: '/product/old-slug-example',
      destination: '/product/new-slug', 
      permanent: true,
    },
  ];
},

另外我也试过客户端重定向,同样没用。我必须用301的核心原因是SEO,业内普遍认为308无法满足SEO需求,必须用301重定向。

解决方案

方案一:手动指定301状态码的redirect函数

Next.js的permanentRedirect封装的是308重定向,如果需要强制返回301,可以直接使用底层的redirect函数,手动传入301状态码:

import { redirect } from 'next/navigation';

export default async function Page({ params: { slug } }: Props) {
  const product = await getProduct(slug);

  if (product.slug !== slug) {
    // 手动指定301状态码实现永久重定向
    redirect(`/product/${product.slug}`, 301);
  }
  // 其他页面渲染逻辑
}

注意:在App Router中,redirect的第二个参数如果传'permanent',部分环境下仍会返回308,直接传数字301可以确保返回正确的状态码。

方案二:用Middleware处理动态全局重定向

如果产品slug是动态更新的,无法提前在next.config.js中配置所有旧slug,推荐使用Next.js Middleware在请求层面处理重定向,这是最灵活的方案:

创建项目根目录的middleware.ts(或.js)文件:

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

export async function middleware(request: NextRequest) {
  const { pathname } = request.nextUrl;
  // 匹配/product/[slug]格式的路径
  const slugMatch = pathname.match(/^\/product\/([^\/]+)$/);
  
  if (slugMatch) {
    const requestedSlug = slugMatch[1];
    // 根据请求的slug获取产品数据,替换成你实际的产品查询逻辑
    const product = await getProduct(requestedSlug);
    
    // 如果产品存在且slug不匹配,返回301重定向
    if (product && product.slug !== requestedSlug) {
      const newUrl = new URL(`/product/${product.slug}`, request.url);
      return NextResponse.redirect(newUrl, { status: 301 });
    }
  }
  
  // 正常请求继续执行
  return NextResponse.next();
}

// 指定Middleware只匹配产品页面路径
export const config = {
  matcher: '/product/:slug*',
};

这个方案的优势是能自动处理所有动态生成的旧slug,不需要手动维护重定向规则,且直接在服务器端返回301状态码,完全满足SEO的需求。

补充说明

Next.js默认用308替代301是因为308会保留原始请求方法(比如POST),但搜索引擎对301的支持更成熟。如果必须使用301,上述两种方案都能解决问题,其中Middleware更适合动态更新的场景。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.23 14:26:10