MST

星途 面试题库

面试题:Next.js 的 getServerSideProps 中的缓存机制与优化策略

在 Next.js 项目中,使用 getServerSideProps 进行数据获取时,如何处理缓存问题以提升性能?请详细说明 Next.js 本身提供的相关机制以及自定义优化策略的实现思路。
39.1万 热度难度
前端开发Next.js

知识考点

AI 面试

面试题答案

一键面试

Next.js 本身提供的缓存机制

  1. In-memory cache

    • Next.js caches the results of getServerSideProps in memory on the server. If the same page is requested again within a short time, and the cache is still valid, the cached data will be used instead of re - running getServerSideProps. This is a built - in performance optimization. For example, if you have a blog page that fetches the latest blog posts using getServerSideProps, and multiple requests come in quickly, the first request will execute the data - fetching logic, and subsequent requests will use the cached result.
  2. Stale - while - Revalidate

    • Next.js supports the Stale - while - Revalidate pattern. You can set a maxAge and staleWhileRevalidate option in the getServerSideProps context.
    • maxAge: This determines how long the cached data is considered fresh. For instance, if you set maxAge: 60, the cached data is fresh for 60 seconds. After this time, the data is considered stale.
    • staleWhileRevalidate: This specifies how long the server can serve stale data while re - validating it in the background. For example, if you set maxAge: 60 and staleWhileRevalidate: 300, for the first 60 seconds, the fresh cached data is served. After 60 seconds, the stale data is served for up to 300 seconds while the server re - runs getServerSideProps to get fresh data. When the new data is available, it replaces the stale data in the cache.
    export async function getServerSideProps(context) {
      const res = await fetch('https://example.com/api/data');
      const data = await res.json();
    
      return {
        props: {
          data
        },
        revalidate: 60 // equivalent to maxAge in this case, and staleWhileRevalidate is not set explicitly here, but can be
      };
    }
    

Custom optimization strategies

  1. External caching
    • Using Redis:
      • Install the ioredis or redis - node library in your Next.js project.
      • In your getServerSideProps, before making the actual data - fetching call (e.g., to an API), check if the data is already in the Redis cache. If it is, return the cached data. If not, make the API call, store the result in Redis, and then return the data.
      import Redis from 'ioredis';
      
      const redis = new Redis();
      
      export async function getServerSideProps(context) {
        const cachedData = await redis.get('my - data - key');
        if (cachedData) {
          return {
            props: {
              data: JSON.parse(cachedData)
            }
          };
        }
      
        const res = await fetch('https://example.com/api/data');
        const data = await res.json();
      
        await redis.set('my - data - key', JSON.stringify(data));
      
        return {
          props: {
            data
          }
        };
      }
      
  2. Cache - busting based on data changes
    • If your data has some kind of versioning or change - tracking mechanism (e.g., a database has a last_updated timestamp), you can incorporate this into your caching strategy.
    • In getServerSideProps, when checking the cache, also check if the version of the data in the cache is up - to - date. If not, re - fetch the data. For example, if your API returns the last_updated timestamp along with the data:
    export async function getServerSideProps(context) {
      const cachedData = await redis.get('my - data - key');
      if (cachedData) {
        const { data, last_updated } = JSON.parse(cachedData);
        const res = await fetch('https://example.com/api/data - version');
        const currentVersion = await res.json();
        if (currentVersion.last_updated === last_updated) {
          return {
            props: {
              data
            }
          };
        }
      }
    
      const res = await fetch('https://example.com/api/data');
      const data = await res.json();
    
      await redis.set('my - data - key', JSON.stringify(data));
    
      return {
        props: {
          data
        }
      };
    }
    
  3. Conditional caching
    • You can cache data conditionally based on user - specific or request - specific factors. For example, if your page has different data based on the user's locale, you can create cache keys that include the locale information.
    export async function getServerSideProps(context) {
      const locale = context.locale;
      const cacheKey = `my - data - ${locale}`;
      const cachedData = await redis.get(cacheKey);
      if (cachedData) {
        return {
          props: {
            data: JSON.parse(cachedData)
          }
        };
      }
    
      const res = await fetch(`https://example.com/api/data?locale=${locale}`);
      const data = await res.json();
    
      await redis.set(cacheKey, JSON.stringify(data));
    
      return {
        props: {
          data
        }
      };
    }