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 策略提升实时性。

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

相关推荐
GIS之路1 小时前
ArcGIS Pro 中的 Notebooks 入门
前端
IT_陈寒2 小时前
React状态管理终极对决:Redux vs Context API谁更胜一筹?
前端·人工智能·后端
Kagol3 小时前
TinyVue 支持 Skills 啦!现在你可以让 AI 使用 TinyVue 组件搭建项目
前端·agent·ai编程
柳杉3 小时前
从零打造 AI 全球趋势监测大屏
前端·javascript·aigc
simple_lau3 小时前
Cursor配置MasterGo MCP:一键读取设计稿生成高还原度前端代码
前端·javascript·vue.js
睡不着先生3 小时前
如何设计一个真正可扩展的表单生成器?
前端·javascript·vue.js
天蓝色的鱼鱼4 小时前
模块化与组件化:90%的前端开发者都没搞懂的本质区别
前端·架构·代码规范
明君879974 小时前
Flutter 如何给图片添加多行文字水印
前端·flutter
leolee184 小时前
Redux Toolkit 实战使用指南
前端·react.js·redux
bluceli4 小时前
React Hooks最佳实践:写出优雅高效的组件代码
前端·react.js