إعلانات TypeScript المعزولة: تعزيز سرعة الـ Monorepo

غالبًا ما تتباطأ عمليات بناء الـ Monorepo بسبب الطريقة التي تتعامل بها TypeScript مع ملفات الإعلانات (declaration files). بشكل افتراضي، تقوم TypeScript بتحليل كل سلسلة استيراد (import chain) قبل إنشاء ملف .d.ts واحد. يؤدي هذا إلى إنشاء طابور انتظار طويل حيث يجب على الحزم انتظار بعضها البعض.

يمكنك إصلاح ذلك باستخدام العلم --isolatedDeclarations.

يسمح هذا العلم بعمليات بناء متوازية. فبدلاً من انتظار التبعيات، تقوم كل حزمة بإنشاء إعلاناتها الخاصة بشكل مستقل. تشهد الفرق زيادة في سرعات البناء تتراوح من 3 إلى 15 ضعفًا.

المشكلة: عادةً ما تقوم TypeScript باستنتاج الأنواع (types) عبر حدود الوحدات (module boundaries). إذا كانت الحزمة A تعتمد على الحزمة B، فيجب على المترجم (compiler) حل B بالكامل قبل أن يتمكن من البدء في A. في الـ monorepo الكبير، تظل معظم الحزم خاملة بينما يعمل المترجم على حزمة تلو الأخرى.

الحل: يغير العلم --isolatedDeclarations القواعد؛ حيث يتطلب منك كتابة تعليقات توضيحية صريحة للأنواع (explicit type annotations) لكل ما تقوم بتصديره (export).

المقايضة: سيتضمن الكود الخاص بك نصًا أكثر. يجب عليك إضافة أنواع الإرجاع (return types) إلى الدوال، والأنواع إلى الثوابت يدويًا. لا يمكنك الاعتماد على المترجم لتخمين هذه الأنواع من الكود الخاص بك.

النتيجة: بما أن كل عملية تصدير لها نوع واضح، فلا يحتاج المترجم إلى النظر في الحزم الأخرى لفهمها، بل يمكنه معالجة كل حزمة في نفس الوقت.

نتائج من العالم الحقيقي:

  • انخفض وقت البناء في monorepo يحتوي على 18 حزمة من 47 ثانية إلى 3.2 ثانية.
  • حقق monorepo يحتوي على 32 حزمة مكاسب بمقدار 8 أضعاف في خطوط أنابيب CI.
  • يتوسع الأداء مع عدد أنوية المعالج (CPU cores) لديك. المزيد من الأنوية يعني بناء المزيد من الحزم في وقت واحد.

كيفية الانتقال:

  1. قم بتفعيل العلم في ملف tsconfig.json الرئيسي وفي إعدادات كل حزمة.
  2. استخدم العلم "composite" للسماح بمراجع المشروع (project references).
  3. أضف أنواع إرجاع صريحة للدوال المصدرة:

// قبل export function add(a: number, b: number) { return a + b; }

// بعد export function add(a: number, b: number): number { return a + b; }

  1. أضف أنواعًا صريحة للثوابت المصدرة:

// قبل export const SETTINGS = { port: 3000 };

// بعد export const SETTINGS: { port: number } = { port: 3000 };

إذا لم تقم بإضافة هذه الأنواع، فسيقوم المترجم بإصدار أخطاء. يضمن ذلك أن تكون أنواعك حتمية (deterministic) وسريعة.

المصدر: https://dev.to/jsmanifest/typescript-isolated-declarations-real-world-performance-gains-in-monorepo-build-times-25g3