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

Next.js使用getStaticPaths时如何实现动态URL掩码替换ID参数

解决方案

这个需求在Next.js中完全可以实现,404问题由动态路由参数配置、Link组件用法、自定义express服务器逻辑三者不匹配导致,按以下步骤调整即可:


方案一:优先推荐(无需自定义express服务器,用Next.js原生路由)

如果没有强制需要自定义express服务器的场景,直接删除server.js中自定义的/products/:id路由,用Next.js原生SSG路由实现,步骤如下:

  1. 调整动态路由文件名
    将pages/products/[id].js重命名为pages/products/[slug].js,其中slug就是需要显示在URL里的product-1这类友好标识,需确保所有产品的slug全局唯一。
  2. 修改GraphQL查询逻辑
    首先在查询所有产品的语句中增加slug字段的查询:
    const GET_ALL_QUERY = gql`
      {
        products {
          id
          slug // 对应后台存储的产品友好路径字段,未提前存储的话也可以在map的时候按规则生成,比如`product-${序号}`
        }
      }
    `;
    
  3. 调整getStaticPaths配置
    把返回的params参数和路由动态段对应:
    export async function getStaticPaths() {
      const paths = await client
        .query({ query: GET_ALL_QUERY })
        .then((data) => {
          const productsData = data.data.products;
          return productsData.map((res, index) => {
            // 未预存slug可直接在此处生成:const slug = `product-${index+1}`
            return { params: { slug: res.slug } };
          });
        })
        .catch((err) => Promise.reject(new Error(err)));
      return {
        paths,
        fallback: false,
      };
    }
    
  4. 调整getStaticProps查询逻辑
    用slug作为参数查询单个产品(需要GraphQL接口支持按slug查询产品,不支持的话可以提前维护一份slug到产品ID的映射表):
    export async function getStaticProps({ params }) {
      try {
        const res = await client.query({
          query: GET_ONE_QUERY,
          variables: { slug: params.slug }, // 替换原有按ID查询的逻辑
        });
        return {
          props: res.data.product,
        };
      } catch (err) {
        throw new Error(err);
      }
    }
    
  5. 简化Link组件写法
    不需要再用as属性,直接拼接slug即可:
    <Link href={`/products/${product.slug}`}>
      产品链接
    </Link>
    

方案二:保留自定义express服务器

如果必须保留自定义express服务器,需要调整路由逻辑,把URL中的slug映射为真实的产品ID:

  1. 提前在内存中维护一份slug到产品ID的映射表,在服务启动时查询所有产品生成:
    // 服务启动时预生成映射表
    let slugToIdMap = {};
    client.query({ query: GET_ALL_QUERY }).then(data => {
      data.data.products.forEach((product, index) => {
        const slug = `product-${index+1}`; // 按实际规则生成slug
        slugToIdMap[slug] = product.id;
      });
    });
    
  2. 修改express路由逻辑,把slug转为真实ID再传给Next.js渲染:
    server.get("/products/:slug", (req, res) => {
      const actualPage = "/products/[id]";
      const realId = slugToIdMap[req.params.slug];
      if(!realId) return res.status(404).send("产品不存在");
      const queryParams = { id: realId };
      app.render(req, res, actualPage, queryParams);
    });
    
  3. Link组件按原有写法即可,注意href对应实际路由:
    <Link href={`/products/${product.id}`} as={`/products/${product.slug}`}>
      产品链接
    </Link>
    

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.07 12:39:01