TypeScript Isolated Declarations: Monorepo کی رفتار میں اضافہ کریں
Monorepo builds اکثر اس وجہ سے سست ہو جاتی ہیں کہ TypeScript declaration files کو کیسے ہینڈل کرتا ہے۔ ڈیفالٹ طور پر، TypeScript ایک بھی .d.ts فائل بنانے سے پہلے ہر import chain کا تجزیہ کرتا ہے۔ اس سے ایک لمبی لائن بن جاتی ہے جہاں پیکیجز کو ایک دوسرے کا انتظار کرنا پڑتا ہے۔
آپ اسے --isolatedDeclarations flag کے ذریعے ٹھیک کر سکتے ہیں۔
یہ flag parallel builds کی اجازت دیتا ہے۔ dependencies کا انتظار کرنے کے بجائے، ہر package اپنی declarations خود مختارانہ طور پر جنریٹ کرتا ہے۔ ٹیمیں build speeds میں 3x سے 15x تک اضافہ دیکھتی ہیں۔
مسئلہ:
TypeScript عام طور پر module boundaries کے پار types کا اندازہ (infer) لگاتا ہے۔ اگر Package A، Package B پر منحصر ہے، تو compiler کو A پر کام شروع کرنے سے پہلے B کو مکمل طور پر resolve کرنا ہوگا۔ ایک بڑے monorepo میں، زیادہ تر packages فارغ بیٹھے رہتے ہیں جبکہ compiler ایک ایک کر کے کام کرتا ہے۔
حل:
--isolatedDeclarations flag قواعد کو بدل دیتا ہے۔ یہ آپ سے تقاضا کرتا ہے کہ آپ جو کچھ بھی export کرتے ہیں اس کے لیے explicit type annotations لکھیں۔
سمجھوتہ (Tradeoff):
آپ کے کوڈ میں متن (text) زیادہ ہوگا۔ آپ کو خود سے functions کے لیے return types اور constants کے لیے types شامل کرنے ہوں گے۔ آپ compiler پر ان types کا اندازہ لگانے کے لیے بھروسہ نہیں کر سکتے۔
نتیجہ:
چونکہ ہر export کی ایک واضح type ہوتی ہے، اس لیے compiler کو انہیں سمجھنے کے لیے دوسرے packages کو دیکھنے کی ضرورت نہیں پڑتی۔ یہ ہر package کو ایک ہی وقت میں process کر سکتا ہے۔
حقیقی دنیا کے نتائج:
- 18 packages والے ایک monorepo میں build time 47 سیکنڈ سے کم ہو کر 3.2 سیکنڈ رہ گیا۔
- 32 packages والے ایک monorepo میں CI pipelines پر 8x بہتری دیکھی گئی۔
- کارکردگی (Performance) آپ کے CPU cores کے ساتھ بڑھتی ہے۔ زیادہ cores کا مطلب ہے کہ زیادہ packages ایک ساتھ build ہوں گے۔
مائیگریٹ کیسے کریں:
- اپنے root
tsconfig.jsonاور ہر package config میں flag کو enable کریں۔ - project references کی اجازت دینے کے لیے "composite" flag استعمال کریں۔
- exported functions میں explicit return types شامل کریں:
// Before
export function add(a: number, b: number) {
return a + b;
}
// After
export function add(a: number, b: number): number {
return a + b;
}
- exported constants میں explicit types شامل کریں:
// Before
export const SETTINGS = { port: 3000 };
// After
export const SETTINGS: { port: number } = { port: 3000 };
اگر آپ یہ types شامل نہیں کرتے ہیں، تو compiler errors دے گا۔ یہ یقینی بناتا ہے کہ آپ کی types deterministic اور تیز ہیں۔
