如何在API路由与getServerSideProps之间共享对象?实例不一致问题
问题解决:Next.js中共享内存对象跨模块实例不一致的问题
问题原因
Next.js在开发模式下会启用热重载,每次代码变更都会重新加载模块;即使在生产模式,API路由和页面的getServerSideProps也可能运行在不同的Node.js worker进程中。这就导致你在match.js中导出的matches数组,在new-match.js和match.jsx里是完全独立的两个实例,互相不共享数据。
另外你的代码还有个逻辑错误:你把对局IDpush进数组,之后却用matches[id]去取——数组是按数字索引存储的,这里应该用对象({})来存储键值对,而不是数组。
解决方案
方案1:使用内存缓存库(推荐开发阶段用)
用node-cache这类轻量内存缓存库来存储对局数据,它能在单Node实例下的多个进程/模块间共享数据。
- 安装依赖:
npm install node-cache
- 修改
match.js:
import NodeCache from 'node-cache'; // 创建缓存实例,可设置过期时间(单位:秒) export const matchCache = new NodeCache({ stdTTL: 3600 });
- 修改
new-match.js:
import { matchCache } from '@/matches'; import { randomUUID } from 'crypto'; export default function handler(req, res) { const id = randomUUID(); // 存储对局数据,可扩展存储棋盘状态、玩家信息等 matchCache.set(id, { status: 'waiting' }); res.redirect(301, `/match?id=${id}`); }
- 修改
match.jsx的getServerSideProps:
import { matchCache } from '@/matches'; export const getServerSideProps = async (context) => { const { id } = context.query; const match = matchCache.get(id); if (!match) { return { redirect: { destination: '/', permanent: false, }, }; } return { props: { match }, }; };
方案2:使用外部数据库(生产环境必备)
如果你的游戏要部署到多实例环境(比如Vercel、AWS多节点),内存缓存会失效,必须用外部数据库(比如Redis、MongoDB、PostgreSQL)来存储对局数据。以Redis为例:
- 安装Redis依赖:
npm install ioredis
- 创建Redis实例文件
redis.js:
import Redis from 'ioredis'; export const redis = new Redis(process.env.REDIS_URL);
- 替换API路由和
getServerSideProps中的缓存操作,改用Redis的set和get方法即可。
方案3:开发阶段临时修复(不推荐生产用)
在开发模式下,你可以通过global对象挂载共享数据,避免模块重载导致的实例不一致:
修改match.js:
// 全局挂载,避免热重载重新实例化 export const matches = global.matches || {}; if (!global.matches) { global.matches = matches; }
注意:这个方法只适用于单Node实例的开发环境,生产环境多进程下依然会失效,且热重载可能导致数据丢失。
内容的提问来源于stack exchange,提问作者Konrad
相关产品推荐
相关产品推荐

