MST

星途 面试题库

面试题:Next.js 动态路由在电商产品详情页及相关推荐的应用

在一个电商项目中,产品详情页的路由为 /product/[productId]。要求在产品详情页展示该产品的相关推荐产品(推荐产品基于产品类别和浏览历史等因素)。请详细阐述实现此功能时,如何通过 Next.js 动态路由获取产品 ID,并且结合服务器端渲染(SSR)或静态站点生成(SSG)技术来高效地渲染产品详情页及相关推荐部分,同时说明如何处理缓存以提升性能。
19.1万 热度难度
前端开发Next.js

知识考点

AI 面试

面试题答案

一键面试

通过 Next.js 动态路由获取产品 ID

在 Next.js 中,动态路由以方括号包裹参数的形式定义。对于 /product/[productId] 这样的路由,我们可以在页面组件中通过 useRouter 钩子或 getStaticPropsgetServerSideProps 的上下文对象来获取 productId

  1. 使用 useRouter 钩子(客户端获取)
    import { useRouter } from 'next/router';
    
    const ProductPage = () => {
      const router = useRouter();
      const { productId } = router.query;
      return (
        <div>
          <p>Product ID: {productId}</p>
        </div>
      );
    };
    
    export default ProductPage;
    
  2. getStaticPropsgetServerSideProps 中获取(服务端获取)
    export async function getStaticProps(context) {
      const { productId } = context.params;
      // 这里可以根据 productId 获取产品数据
      return {
        props: {
          productId
        },
        revalidate: 60 // 如果使用增量静态再生,设置重新验证时间
      };
    }
    
    export async function getServerSideProps(context) {
      const { productId } = context.params;
      // 这里可以根据 productId 进行服务器端数据获取
      return {
        props: {
          productId
        }
      };
    }
    
    const ProductPage = ({ productId }) => {
      return (
        <div>
          <p>Product ID: {productId}</p>
        </div>
      );
    };
    
    export default ProductPage;
    

结合 SSR 或 SSG 技术高效渲染产品详情页及相关推荐部分

  1. 静态站点生成(SSG)
    • 数据获取:在 getStaticProps 函数中,根据获取到的 productId 从数据库或 API 中获取产品详情数据以及相关推荐产品数据。例如:
    import { getAllProducts, getProductById } from '../lib/api';
    
    export async function getStaticProps(context) {
      const { productId } = context.params;
      const product = await getProductById(productId);
      const relatedProducts = await getAllProducts({ category: product.category });
      return {
        props: {
          product,
          relatedProducts
        },
        revalidate: 60 // 可选,设置增量静态再生时间
      };
    }
    
    export async function getStaticPaths() {
      const products = await getAllProducts();
      const paths = products.map(product => ({
        params: { productId: product.id.toString() }
      }));
      return { paths, fallback: false };
    }
    
    const ProductPage = ({ product, relatedProducts }) => {
      return (
        <div>
          <h1>{product.title}</h1>
          {/* 展示产品详情 */}
          <h2>Related Products</h2>
          {relatedProducts.map(related => (
            <div key={related.id}>{related.title}</div>
          ))}
        </div>
      );
    };
    
    export default ProductPage;
    
    • 优势:SSG 在构建时生成 HTML 页面,适合内容变化不频繁的产品详情页。可以极大提高页面加载速度,因为用户直接获取预生成的 HTML。
    • 适用场景:适用于大多数电商产品详情页,尤其是产品信息和推荐相对稳定,不需要实时更新的情况。
  2. 服务器端渲染(SSR)
    • 数据获取:在 getServerSideProps 函数中,同样根据 productId 获取产品详情和相关推荐数据。
    import { getAllProducts, getProductById } from '../lib/api';
    
    export async function getServerSideProps(context) {
      const { productId } = context.params;
      const product = await getProductById(productId);
      const relatedProducts = await getAllProducts({ category: product.category });
      return {
        props: {
          product,
          relatedProducts
        }
      };
    }
    
    const ProductPage = ({ product, relatedProducts }) => {
      return (
        <div>
          <h1>{product.title}</h1>
          {/* 展示产品详情 */}
          <h2>Related Products</h2>
          {relatedProducts.map(related => (
            <div key={related.id}>{related.title}</div>
          ))}
        </div>
      );
    };
    
    export default ProductPage;
    
    • 优势:SSR 在每次请求时生成 HTML,能够实时获取最新的数据,适合产品信息或推荐可能频繁变化的场景。
    • 适用场景:适用于产品数据更新频繁,或者推荐算法依赖实时用户行为数据的情况。

处理缓存以提升性能

  1. 客户端缓存
    • 浏览器缓存:设置合适的 HTTP 缓存头,如 Cache - ControlETag。对于静态资源(如图片、CSS、JS),可以设置较长的缓存时间,因为它们通常不会频繁变化。对于产品详情页的 HTML,可以根据产品更新频率设置合理的缓存时间。例如,对于变化不频繁的产品,可以设置 Cache - Control: public, max - age = 3600(缓存 1 小时)。
    • 前端状态管理缓存:使用 Redux 或 MobX 等状态管理库时,可以在客户端缓存产品数据。当用户在应用内导航到其他产品详情页又返回时,直接从客户端状态中获取数据,避免重复请求。
  2. 服务器端缓存
    • 数据库缓存:如果使用 SQL 数据库,可以利用数据库自带的查询缓存机制。例如,MySQL 有查询缓存功能,可以缓存查询结果,当下次相同查询到来时直接返回缓存结果。对于 NoSQL 数据库如 Redis,可以手动将常用的产品数据和推荐数据缓存到 Redis 中。当请求到达时,先检查 Redis 中是否有缓存数据,如果有则直接返回,避免数据库查询。
    • 应用层缓存:在 Node.js 应用中,可以使用 lru - cache 等库实现简单的内存缓存。在获取产品数据和推荐数据的函数中,检查缓存中是否已经存在相应数据,如果存在则直接返回缓存数据,否则从数据库或 API 获取并更新缓存。例如:
    const LRU = require('lru - cache');
    const cache = new LRU({
      max: 100, // 最大缓存项数
      maxAge: 1000 * 60 * 10 // 缓存项的最大存活时间,10 分钟
    });
    
    async function getProductById(productId) {
      let product = cache.get(productId);
      if (!product) {
        product = await // 从数据库或 API 获取产品数据
        cache.set(productId, product);
      }
      return product;
    }