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

如何在NextJS中配置含分类与标题的URL并加载[id].js页面?

实现方案

有两种可行方式能满足你的需求:既保留SEO友好的URL结构,又复用现有的posts/[id].js页面。

方法一:用Next.js Rewrites路由重写

这是最省心的方案,不用修改现有页面结构,通过配置让长URL指向原页面。

在项目根目录的next.config.js中添加如下配置:

/** @type {import('next').NextConfig} */
const nextConfig = {
  async rewrites() {
    return [
      {
        source: '/posts/:id/:cat/:title',
        destination: '/posts/:id', // 把长URL重写到原[id].js页面
      },
    ];
  },
};

module.exports = nextConfig;

配置生效后,访问https://example.com/posts/123/tech/hello-world时,会实际渲染posts/[id].js页面,同时你可以通过useRouter获取cat和title参数:

// posts/[id].js 中
import { useRouter } from 'next/router';

export default function Post() {
  const router = useRouter();
  const { id, cat, title } = router.query;

  // 业务逻辑依然只用id,cat和title仅用于SEO配置
  return (
    <div>
      <h1>{title}</h1>
      <p>分类:{cat}</p>
      {/* 文章内容 */}
    </div>
  );
}

方法二:调整文件路由结构(捕获所有动态段)

如果不想依赖配置文件,也可以通过调整路由文件结构实现:

  1. 将原posts/[id].js移动到posts/[id]/[...seo].js(seo是自定义命名,可随意修改)
  2. 在新文件中通过useRouter获取所有参数:
import { useRouter } from 'next/router';

export default function Post() {
  const router = useRouter();
  const { id, seo } = router.query;
  // seo是数组,格式为[cat, title]
  const [cat, title] = seo || [];

  // 业务逻辑依旧基于id处理
  return (
    <div>
      <h1>{title}</h1>
      <p>分类:{cat}</p>
      {/* 文章内容 */}
    </div>
  );
}

这种方式下,https://example.com/posts/123(仅id)和https://example.com/posts/123/tech/hello-world(带分类和标题)都会渲染同一个页面,完全适配你的SEO和业务需求。

额外提示

不管用哪种方法,记得在页面的SEO元标签中用上cat和title参数,最大化SEO效果:

import Head from 'next/head';

export default function Post() {
  // ...获取参数的代码
  return (
    <>
      <Head>
        <title>{title} - {cat} | 你的网站名称</title>
        <meta name="description" content={`${title},属于${cat}分类的文章`} />
      </Head>
      {/* 页面内容 */}
    </>
  );
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.18 04:45:37