NextJS开发环境下Map实例因热重载重置问题求助
Next.js开发环境热重载导致Map实例重置问题
在Next.js开发环境中,热重载会重置downloadTokens这个Map实例,生产构建运行后该问题消失。以下是相关代码、调试日志及解决思路:
相关代码
1. Map模块代码
const downloadTokens = new Map<string, string>(); console.log("instance created") export default downloadTokens;
2. API处理器代码
import * as fs from 'fs'; import {NextApiRequest, NextApiResponse} from "next"; import {getProductCode} from "@/store/schematic/DownloadToken"; export default async function handler(req: NextApiRequest, res: NextApiResponse) { if (req.method != 'GET') return res.status(400).json({status: 400, messages: "Invalid method, instead make a get request!"}) const downloadToken = req.headers['authorization']; if (!downloadToken) return res.status(400).json({status: 400, messages: "Invalid token!"}) const productCode = getProductCode(downloadToken as string); const fileName = `${productCode}.schematic` const fileBuffer = fs.readFileSync(`${process.cwd()}/data/schematics/${fileName}`); if (fileBuffer.length == 0) return res.status(500).json({status: 500, messages: "Unable to find the schematic file. Please contact the administrator."}) const blob = Buffer.from(fileBuffer); res.setHeader("Content-Type", "application/octet-stream"); res.setHeader("Content-Disposition", `attachment; filename=${fileName}`) return res.status(200).send(blob); }
3. DownloadToken工具函数
import {randomUUID} from "node:crypto"; import downloadTokens from "./DownloadTokenMap"; console.log(`downloadTokens instance : ${downloadTokens}`); export function generate(productCode: string): string { const token = randomUUID(); downloadTokens.set(token, productCode); console.log(downloadTokens) return token; } export function getProductCode(token: string): string | null { const productCode = downloadTokens.get(token); console.log(downloadTokens) return productCode ? productCode : null; }
调试日志
✓ Compiled /api/capture in 111ms (145 modules) instance created downloadTokens instance : [object Map] Map(1) { 'b85801bd-6e9c-4af7-aa4a-35d5530b5ed9' => 'SC-SKYBLOCK_LOBBY-1' } POST /api/capture?orderId=xxxx 200 in 2132ms ✓ Compiled in 305ms (762 modules) ✓ Compiled /api/download/schematic in 44ms (148 modules) instance created downloadTokens instance : [object Map] Map(0) {} ⨯ Error: ENOENT: no such file or directory, open '/Users/...
原因及解决思路
问题根源
Next.js开发环境的热重载机制会在代码变更时重新加载相关模块,模块级别的变量(如这个Map实例)会在每次重载时重新初始化,导致之前存储的token数据丢失。生产环境中代码是一次性构建加载,不存在模块重载,因此问题不会出现。
解决方案
使用Node.js全局对象存储
将Map挂载到global对象上,确保模块重载时实例不会被重置:// DownloadTokenMap.ts declare global { var downloadTokens: Map<string, string>; } // 仅在全局对象未初始化时创建实例 if (!global.downloadTokens) { global.downloadTokens = new Map<string, string>(); console.log("instance created"); } export default global.downloadTokens;该方案适合开发环境临时使用,注意添加全局变量的TypeScript类型声明以避免语法报错。
改用持久化外部存储
如果需要数据在服务重启后保留,或者适配多实例部署场景,建议使用Redis、数据库等外部存储替代内存Map,开发和生产环境都能保持数据一致性。禁用特定模块热重载(不推荐)
可在next.config.js中配置,对包含Map的模块禁用热重载,但会降低开发效率,仅作为临时应急方案。
内容的提问来源于stack exchange,提问作者Maxigame99
相关产品推荐
相关产品推荐

