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

Next.js中Middleware与API路由的单例类实例为何不同?

问题

我编写了一个用于存储计数器的单例类CounterSingleton,代码如下:

export class CounterSingleton {
  private static instance: CounterSingleton;
  private count: number;

  private constructor() {
    this.count = 0;
  }

  public static getInstance(): CounterSingleton {
    if (!CounterSingleton.instance) {
      CounterSingleton.instance = new CounterSingleton();
    }
    return CounterSingleton.instance;
  }

  public increment(): void {
    this.count++;
  }

  public getCount(): number {
    return this.count;
  }
}

在Next.js的API路由中调用该单例时,计数器能够正常递增:

// Next.js API route support: https://nextjs.org/docs/api-routes/introduction
import { CounterSingleton } from "@/utility/counter";
import type { NextApiRequest, NextApiResponse } from "next";

type Data = {
  counter: number;
};

export default function handler(
  req: NextApiRequest,
  res: NextApiResponse<Data>
) {
  const counter = CounterSingleton.getInstance();
  counter.increment();
  res.status(200).json({ counter: counter.getCount() });
}

首次API调用返回:{ counter: 1 },第二次返回:{ counter: 2 }。

但在Middleware中调用同一个单例类时,计数器始终返回0,Middleware代码如下:

import { NextResponse } from "next/server";
import { CounterSingleton } from "./utility/counter";

export function middleware() {
  const counter = CounterSingleton.getInstance();
  console.log(counter.getCount());
  return NextResponse.next();
}

请问为何Middleware与API路由中的单例类实例不同?

原因分析
  • 进程级隔离导致状态不共享:Next.js的Middleware和API路由运行在完全独立的进程中,各自拥有独立的内存空间。单例的状态存储在进程内存里,所以两者的单例实例完全独立,状态互不影响。
  • Middleware的运行时特性:Middleware属于请求前置拦截逻辑,它的代码会被打包到单独的运行时环境中,和API路由的Node.js运行时不共享任何内存。即使是单例模式,每次Middleware所在进程启动时都会重新初始化实例,所以计数器始终保持初始值0。
  • API路由的进程复用特性:API路由运行在Node.js环境中,服务器运行期间同一进程会处理多个请求,单例的状态会在进程内的请求之间共享,因此多次调用能实现计数器递增。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.21 21:32:40