next.js中实现缓存

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

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

⚙️ 二、典型应用场景

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

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

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

方式一 :使用内存缓存(最简单) 使用 Maplru-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 策略提升实时性。

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

相关推荐
未来之窗软件服务5 小时前
一体化系统(九)智慧社区综合报表——东方仙盟练气期
大数据·前端·仙盟创梦ide·东方仙盟·东方仙盟一体化
陈天伟教授8 小时前
人工智能训练师认证教程(2)Python os入门教程
前端·数据库·python
信看9 小时前
NMEA-GNSS-RTK 定位html小工具
前端·javascript·html
Tony Bai9 小时前
【API 设计之道】04 字段掩码模式:让前端决定后端返回什么
前端
苏打水com9 小时前
第十四篇:Day40-42 前端架构设计入门——从“功能实现”到“架构思维”(对标职场“大型项目架构”需求)
前端·架构
king王一帅9 小时前
流式渲染 Incremark、ant-design-x markdown、streammarkdown-vue 全流程方案对比
前端·javascript·人工智能
苏打水com10 小时前
第十八篇:Day52-54 前端跨端开发进阶——从“多端适配”到“跨端统一”(对标职场“全栈化”需求)
前端
Bigger10 小时前
后端拒写接口?前端硬核自救:纯前端实现静态资源下载全链路解析
前端·浏览器·vite
BD_Marathon10 小时前
【JavaWeb】路径问题_前端绝对路径问题
前端