MST
星途 面试题库

面试题:Next.js API Routes 缓存策略与页面性能的平衡优化

当应用中有多个 API Routes 且每个接口对缓存需求不同时,如何制定合理的缓存策略,既保证接口性能,又不影响页面的实时性?请结合 Next.js 的缓存和优化技巧,详细说明设计思路和实现步骤。
33.5万 热度难度
前端开发Next.js

知识考点

AI 面试

面试题答案

一键面试

设计思路

  1. 分析接口需求:对每个 API Route 进行细致分析,明确其数据变化频率、实时性要求等。例如,展示系统配置信息的接口,数据变化不频繁,可长时间缓存;而展示实时用户活动的接口,则需低延迟甚至不缓存。
  2. 选择缓存类型
    • 短期缓存:对于数据变化相对频繁但并非完全实时的接口,如商品库存(会随订单逐渐减少,但不是立即更新),可设置较短的缓存时间,比如几分钟。
    • 长期缓存:针对数据极少变动的接口,像网站的版权信息接口,缓存时间可设置为几天甚至几周。
    • 无缓存:对于实时性要求极高的接口,如实时聊天消息接口,不进行缓存。
  3. 结合 Next.js 特性
    • In-Browser Caching:利用浏览器缓存机制,对于静态资源以及部分接口响应可设置合适的 Cache-Control 头,让浏览器进行缓存。这可以减少重复请求,提高页面加载速度。
    • ISR(Incremental Static Regeneration):适用于数据有一定时效性但不需要完全实时更新的页面。通过在 getStaticPropsgetStaticPaths 中设置 revalidate 参数,Next.js 会在指定时间间隔后重新生成页面静态内容,保证数据的相对新鲜度。
    • SSR(Server-Side Rendering):对于实时性要求高的页面或接口,采用 SSR 方式。在服务器端实时获取数据,确保每次请求都能得到最新数据。

实现步骤

  1. 设置缓存头:在 Next.js 中,可通过自定义 API Route 处理函数来设置 Cache-Control 头。例如:
export default function handler(req, res) {
    // 假设这是一个数据变化不频繁的接口
    res.setHeader('Cache-Control', 'public, max-age=3600'); // 缓存1小时
    // 接口逻辑,返回数据
    res.status(200).json({ data: 'your data' });
}
  1. ISR 实现:在页面组件的 getStaticProps 函数中使用 revalidate
export async function getStaticProps() {
    const response = await fetch('your-api-url');
    const data = await response.json();
    return {
        props: {
            data
        },
        revalidate: 60 // 每分钟重新验证数据
    };
}
  1. SSR 实现:在页面组件的 getServerSideProps 函数中实时获取数据。
export async function getServerSideProps(context) {
    const response = await fetch('your-api-url');
    const data = await response.json();
    return {
        props: {
            data
        }
    };
}
  1. 缓存分层:可以结合 CDN 进行缓存分层。CDN 可以缓存静态资源和部分 API 响应数据,进一步减轻服务器压力,提高全球范围内用户的访问速度。同时,在服务器端也可以使用本地缓存(如 Redis)来缓存经常访问的数据,减少数据库查询次数。例如,在 Node.js 应用中使用 ioredis 库连接 Redis 服务器:
const Redis = require('ioredis');
const redis = new Redis();

export default async function handler(req, res) {
    const cacheKey = 'your-cache-key';
    let data = await redis.get(cacheKey);
    if (data) {
        res.status(200).json(JSON.parse(data));
    } else {
        const response = await fetch('your-api-url');
        data = await response.json();
        await redis.set(cacheKey, JSON.stringify(data));
        res.status(200).json(data);
    }
}