NestJS — Node.js للمؤسسات

ModuleRef والتحميل الكسول والحل الديناميكي

18 دقيقة الدرس 51 من 80

ModuleRef والتحميل الكسول والحل الديناميكي

ينبغي حقن معظم الاعتماديات عبر الباني، لكن التطبيقات المتقدمة تحتاج أحياناً إلى بحث ديناميكي عن المزوّدات: إضافات، تكاملات اختيارية، خدمات خاصة بالمستأجر، أو وحدة لا تُحمّل إلا عند طلب ميزة. تغطي ModuleRef و LazyModuleLoader هذه الحالات.

الفكرة الأساسية

تدور هذه الميزة حول التحكم في كيفية تنظيم التطبيق وسلوكه وقت التشغيل. النقاط التالية هي ما يجب أن يعرفه المطور قبل استخدامها في مشروع حقيقي:

  • تجلب ModuleRef.get() مزوداً موجوداً مسبقاً بالرمز داخل سياق الوحدة الحالية.
  • يسمح تمرير { strict: false } بحل مزود من السياق العام للتطبيق، لكن الإفراط فيه يخفي مشاكل حدود الوحدات.
  • تنشئ moduleRef.resolve() أو تجلب مزودات ذات نطاق باستخدام ContextId، وهذا مهم للاعتماديات بنطاق الطلب.
  • يحمّل LazyModuleLoader وحدة كاملة عند الحاجة بدلاً من تحميلها وقت إقلاع التطبيق.
  • الحل الديناميكي قوي لكنه مخصص غالباً لكود الإطار والإضافات والتكاملات لا لخدمات العمل العادية.

مثال عملي

يوضح المثال التالي الشكل العملي للفكرة داخل مشروع NestJS. ليست الغاية حفظ الكود، بل فهم مكانه في المعمارية:

@Injectable() export class ReportPluginRunner { constructor( private readonly moduleRef: ModuleRef, private readonly lazyLoader: LazyModuleLoader, ) {} async runHeavyExport() { const moduleRef = await this.lazyLoader.load(() => ExportModule); const exporter = moduleRef.get(CsvExportService); return exporter.generate(); } }
ملاحظة تصميمية: يبقى حقن الباني هو الافتراضي لأنه صريح وقابل للاختبار. استخدم ModuleRef عندما لا يمكن معرفة الاعتمادية وقت الترجمة أو لا يجب إنشاؤها أثناء الإقلاع.

قائمة تطبيق إنتاجية

  • فضّل حقن الباني للخدمات العادية.
  • استخدم LazyModuleLoader للوحدات الثقيلة قليلة الاستخدام.
  • تجنب { strict: false } إلا عند الحاجة المقصودة للبحث عبر الوحدات.
  • استخدم ContextIdFactory عند حل مزودات بنطاق الطلب يدوياً.
قاعدة عملية: إذا جعلت الميزة الحدود أوضح والاختبارات أسهل فهي اختيار جيد. إذا أخفت التبعيات أو صعّبت التتبع، فأعد التصميم.

الخلاصة

يغطي هذا الدرس جزءاً متقدماً من NestJS يجب فهمه عند بناء تطبيقات مؤسسية. ركّز على الحدود الواضحة، والسلوك القابل للاختبار، واختيار الأداة المناسبة للسياق بدلاً من استخدام كل ميزة في كل مكان.