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
相关产品推荐
相关产品推荐

