You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Node.js为何生成单例类两个实例?Next.js开发环境问题求助

问题原因

Next.js 开发模式的**热重载(Fast Refresh)**机制是核心诱因:

  • 开发时代码变更会触发模块重新编译加载,模块级导出的单例类会被重新实例化。
  • 首次连接SSE端点时,使用的是旧模块的SSE实例(已注册客户端);发送消息时,若代码变更触发过热重载,此时outgoing.ts会加载新模块的SSE实例(客户端列表为空),导致消息无法推送。
  • 刷新页面后,客户端连接到新模块的SSE实例,后续发送消息也复用该实例,功能恢复正常。
解决方案

方案1:将单例实例挂载到全局对象(推荐)

修改serverSentEvents.ts的单例实现,把实例存储在globalThis(Node.js全局对象)上,避免模块热重载时丢失实例:

class SSE {
  private clients: Map<string, Response> = new Map();

  private constructor() {}

  static getInstance(): SSE {
    const global = globalThis as typeof globalThis & { sseInstance?: SSE };
    if (!global.sseInstance) {
      global.sseInstance = new SSE();
    }
    return global.sseInstance;
  }

  // 注册客户端
  registerClient(clientId: string, res: Response) {
    this.clients.set(clientId, res);
  }

  // 发送消息
  send(clientId: string, message: string) {
    const res = this.clients.get(clientId);
    if (res) {
      res.write(`data: ${JSON.stringify(message)}\n\n`);
    }
  }
}

export default SSE.getInstance();

方案2:排除SSE模块参与热重载

在next.config.js中配置,让serverSentEvents.ts模块跳过开发模式的热重载,确保始终使用同一个实例:

/** @type {import('next').NextConfig} */
const nextConfig = {
  webpack: (config, { dev }) => {
    if (dev) {
      config.module.rules.push({
        test: /serverSentEvents\.ts$/,
        use: ['cache-loader'],
        include: /lib\/sse/,
      });
    }
    return config;
  },
};

module.exports = nextConfig;

安装依赖:

npm install cache-loader --save-dev

额外说明

  • 开发模式下,若修改了SSE类的核心逻辑,需手动重启开发服务器才能生效(因模块被排除在热重载外)。
  • 生产模式无热重载机制,该异常不会在上线环境出现。

内容的提问来源于stack exchange,提问作者sincerely_manny

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.08 15:15:38