node.js - نمیتوان از متغیر مشترک در NextJS 15 استفاده کرد


کد کمینه

https://codesandbox.io/p/devbox/vqfy8t

مشکل

من سعی میکنم یک کلاس (Vault) را نمونهسازی کنم

من میخواستم یک متغیر بین دو مسیر در nextJS به اشتراک گذاشته شود
/send-email/
    route.ts
/confirm-email/
    route.ts

این متغیر کارش نگه داشتن شناسههای ایمیل همراه با یک کد تولید شده است و تایید میکند که آیا کد معتبر است یا نامعتبر.

این نحو برای نمونهسازی کلاس خزانه است!

let instance: VaultType | undefined = undefined;
export function getOrCreateVaultInstance(keys?: Map<string, string>): Vault {
  if (instance === undefined) {
    console.info("✨ Creating a new vault instance ✨");
    instance = new Vault(keys);
  }

  return instance;
}

اینگونه است که من از گاوصندوق فراخوانی میکنم (داخل هر دو send-email و confirm-email):

const vault = deps?.vault || getOrCreateVaultInstance();

deps پارامترهای اختیاری هستند که به توابع مسیر ارسال میشوند. این فقط برای اهداف آزمایشی است.

اما چرا گنجه دو بار نمونهسازی میشود؟ من میخواهم گنجه فقط یک نمونه بسازد و این نمونه بین دو مسیر دیگر یا هر مسیر ضروری دیگری به اشتراک گذاشته شود.

و چرا این اتفاق میافتد؟
آنچه میخواهم

ایجاد یک نمونه واحد بین دو مسیر NextJs.

فکر میکنم مشکل مربوط به NextJS باشد. من روی آخرین نسخه NextJS هستم (v.15)

از آنجایی که chatGPT نتوانست کمک کند... من سعی کردم کلاس و نوع آن را به فایل دیگری منتقل کنم. و یک فایل vaultSingleton.ts ایجاد کردم تا فقط یک بار ساخته شود.

من سعی کردهام یک بار برای هر فایل مسیر getOrCreateVaultInstance را فراخوانی کنم و سپس از آن اینگونه استفاده کنم:

const vaultInstance = getOrCreatVaultInstance();

function POST(req, res, deps){ 
   const vault = deps?.vault || vaultInstance;
   // ...
}

هیچ چیزی تغییر نکرد. هنوز console.info("✨ در حال ایجاد یک نمونه جدید از والوت ✨"); را دو بار دیدم...

کد حداقلی: https://codesandbox.io/p/devbox/vqfy8t

پاسخ شماره ۱

ممکن است به دلیل کش کردن ماژول در Node.js باشد
https://nodejs.org/api/modules.html#modules_caching

ملاحظات مربوط به کش کردن ماژول

ماژولها بر اساس نام فایل مشخص شدهشان کش میشوند. از آنجایی که ممکن است ماژولها بر اساس موقعیت ماژول فراخواننده (بارگذاری از پوشههای node_modules) به نام فایل متفاوتی حل شوند، تضمینی وجود ندارد که require('foo') همیشه همان شیء دقیق را برگرداند، اگر قرار باشد به فایلهای مختلف حل شود.

نظریه من این است که send و confirm همان ماژول vault را از مسیرهای مختلف وارد میکنند، به همین دلیل فکر میکنم Node.js آنها را به عنوان ماژولهای جداگانه میشناسد و برای هر واردکردن یک نمونه جدید از Vault ایجاد میکند، حتی اگر از همان ماژول استفاده کنند. این موضوع بهتر در اینجا توضیح داده شده است.

send مسیر: app/api/send/../vault/vault

تأیید مسیر: app/api/confirm/../vault/vault

راهحلی که پیدا کردم استفاده از شیء globalThis است

من سعی کردم از globalThis در کد سندباکس شما استفاده کنم و با این کد فقط یک بار ✨ ایجاد یک نمونهی جدید از وانتی ✨ را ثبت کرد:

// Store the instance on globalThis for a singleton pattern
export function getOrCreateVaultInstance(keys?: Map<string, string>): Vault {
  if (!globalThis.__vaultInstance) {
    console.info(`✨ Created a vault instance ✨`);
    globalThis.__vaultInstance = new Vault(keys);
  }

  return globalThis.__vaultInstance;
}

// Type assertion to expose the instance as the Vault type
declare global {
  var __vaultInstance: Vault | undefined;
}

در اینجا چند سوال وجود دارد که من پاسخ آنها را گرفتم:
الگوی Singleton در Node.js - آیا لازم است؟

امیدوارم این کمک کند :)