next.js中实现缓存

🧩 一、缓存的核心思路 在 Fastify + Next.js 场景下,缓存通常分为三层:

缓存层级 缓存内容 适用场景
1. HTTP Header 缓存(浏览器/CDN 层) 静态资源、HTML 页面 CDN 前置缓存、浏览器缓存控制
2. 内存缓存(进程内) 接口数据、配置、语言包、皮肤数据 小规模、高并发场景下的快速命中
3. 外部缓存(Redis 等) 登录态、用户信息、接口响应 分布式服务场景,多节点共享

⚙️ 二、典型应用场景

✅ 常见你在自定义 Fastify 服务器中会缓存的内容包括:

  • /fePublicInfo 这样的公共接口(语言包、皮肤配置)
  • 登录用户的简要信息(token→user)
  • SSR 数据预加载(例如首页接口)
  • 远程配置文件、CDN JSON 等

🧠 三、Fastify 缓存的常用实现方式

方式一 :使用内存缓存(最简单) 使用 Map 或 lru-cache 作为本地缓存。

✅ 示例:缓存 /fePublicInfo 响应 10 分钟

kotlin 复制代码
import Fastify from 'fastify'
import LRU from 'lru-cache'

const fastify = Fastify()
const cache = new LRU({
  max: 100,           // 最多缓存 100 条
  ttl: 1000 * 60 * 10 // 缓存 10 分钟
})

fastify.get('/api/fePublicInfo', async (req, reply) => {
  const cacheKey = 'fePublicInfo'
  const cached = cache.get(cacheKey)

  if (cached) {
    // 命中缓存
    reply.header('x-cache', 'HIT')
    return cached
  }

  // 缓存未命中 → 请求远程服务
  const res = await fetch('https://api.xxx.com/fePublicInfo')
  const data = await res.json()

  // 写入缓存
  cache.set(cacheKey, data)
  reply.header('x-cache', 'MISS')
  return data
})

fastify.listen({ port: 3000 })

🔹 优点:超简单、适合小规模服务

🔹 缺点:内存缓存无法跨进程共享,适合单实例部署

方式二:使用 Redis 缓存(推荐生产环境) ✅ 示例:基于 Redis 缓存 API 响应

javascript 复制代码
import Fastify from 'fastify'
import Redis from '@fastify/redis'

const fastify = Fastify()

fastify.register(Redis, { host: '127.0.0.1', port: 6379 })

fastify.get('/api/fePublicInfo', async (req, reply) => {
  const cacheKey = 'fePublicInfo'
  const cached = await fastify.redis.get(cacheKey)

  if (cached) {
    reply.header('x-cache', 'HIT')
    return JSON.parse(cached)
  }

  const res = await fetch('https://api.xxx.com/fePublicInfo')
  const data = await res.json()

  // 缓存 10 分钟
  await fastify.redis.set(cacheKey, JSON.stringify(data), 'EX', 60 * 10)
  reply.header('x-cache', 'MISS')
  return data
})

🔹 优点:跨实例共享、持久化、可限流

🔹 缺点:多一次网络开销

方式三:对 SSR 页面做缓存(全页缓存) 适用于不经常变化的 SSR 页面,比如首页或营销页。

✅ 示例:缓存 SSR 渲染结果

javascript 复制代码
import Fastify from 'fastify'
import LRU from 'lru-cache'
import next from 'next'

const dev = process.env.NODE_ENV !== 'production'
const app = next({ dev })
const handle = app.getRequestHandler()

const fastify = Fastify()
const pageCache = new LRU({ max: 100, ttl: 1000 * 60 * 5 }) // 5分钟缓存

fastify.get('/', async (req, reply) => {
  const cacheKey = 'page:/'

  if (pageCache.has(cacheKey)) {
    reply.header('x-cache', 'HIT').type('text/html')
    return reply.send(pageCache.get(cacheKey))
  }

  const html = await app.renderToHTML(req.raw, reply.raw, '/', req.query)
  pageCache.set(cacheKey, html)

  reply.header('x-cache', 'MISS').type('text/html')
  reply.send(html)
})

fastify.all('*', (req, reply) => handle(req.raw, reply.raw))

🔹 优点:显著提升 SSR 页面性能

🔹 缺点:要注意缓存失效逻辑(如语言切换、登录态)

方式四:利用 HTTP 缓存头(CDN + 浏览器)

rust 复制代码
reply.header('Cache-Control', 'public, max-age=300, stale-while-revalidate=60')

这告诉 CDN/浏览器:

  • 正常缓存 300 秒;
  • 超时后可继续用旧缓存 60 秒,同时异步更新。

综合最佳实践 在中大型项目中,推荐组合策略:

层级 缓存内容 技术
CDN 层 图片、静态资源 Cache-Control
Fastify 层 公共接口 Redis / LRU
SSR 层 页面 HTML LRU / Redis
客户端层 用户操作数据 localStorage / SW
  • 静态资源通过 CDN + Cache-Control 头;

  • 接口数据通过 Fastify 插件(LRU 或 Redis)缓存;

  • SSR 页面通过 LRU 做全页缓存;

  • 并结合 stale-while-revalidate 策略提升实时性。

    这样既保证了性能,也避免缓存击穿问题。

相关推荐
hkNaruto1 小时前
【AI】基于大模型的AI游戏地图生成、控制方案:AI Native Game Harness 迁移操作手册
前端·人工智能·游戏
IT_陈寒1 小时前
Java序列化踩坑记:对象循环引用让我加班两小时
前端·人工智能·后端
Acro2 小时前
快给macOS 上的Grok Bot换一套皮肤
前端
flash俊杰2 小时前
双引擎 OCR 编排:逐页判定、视觉优先、partial 语义与三层超时
前端
计算机魔术师2 小时前
Reddit 每周被 Google 偷走 100 万次点击,CEO 摊牌了
前端
前端繁华如梦2 小时前
用 React Three Fiber 做一栋能编辑的教学楼数字孪生
前端
前端繁华如梦2 小时前
用 React Three Fiber 做一套智慧医院数字孪生:编辑器、大屏和 BIM 浏览器
前端
俊昭喜喜里3 小时前
理解全局跨域CORS配置
前端
锋行天下6 小时前
DeepSeek写Langgraph就是个大傻逼,一本正经胡说八道
前端·人工智能·后端
jktantan6 小时前
每个节点 41 字节:把一棵百万节点树拆进 14 个 typed array
前端·javascript·vue.js·算法·typescript