ایک فرنٹ اینڈ ٹیم نے ایک ٹائپ سیف (type-safe) API-mocking لیئر متعارف کروائی ہے جو صرف ڈویلپمنٹ کے دوران کام کرتی ہے۔ Axios interceptors اور Vite کے tree-shaking کا استعمال کرتے ہوئے، پروڈکشن بنڈل (production bundle) کو متاثر نہیں کیا جاتا۔ انجینئرز بیک اینڈ اینڈ پوائنٹس (backend endpoints) کا انتظار کرتے ہوئے اپنے معمول کے پیٹرنز کے ساتھ ڈیٹا حاصل کرتے ہیں، اور پھر اصل API تک پہنچنے کے لیے صرف ایک انوائرمنٹ فلیگ (environment flag) تبدیل کر دیتے ہیں۔

ٹیم کو موکنگ (mocking) کے لیے بہتر طریقے کی ضرورت کیوں تھی

جب بیک اینڈ روٹ (backend route) نامکمل ہو تو فرنٹ اینڈ ڈویلپرز کو رکاوٹ کا سامنا کرنا پڑتا ہے۔ فوری حل—کسی کمپوننٹ کے اندر رسپانس کو ہارڈ کوڈ کرنا یا پورے UI میں if (process.env.NODE_ENV === 'development') بلاکس کا استعمال کرنا—ایپ کو تو چلائے رکھتا ہے لیکن تکنیکی قرض (technical debt) چھوڑ جاتا ہے۔ وہ موک آبجیکٹس (mock objects) کمپوننٹ کے لاجک کا حصہ بن جاتے ہیں، پروڈکشن میں جعلی ڈیٹا بھیجنے کا خطرہ بڑھاتے ہیں، اور کوڈ کو پڑھنا اور ٹیسٹ کرنا مشکل بنا دیتے ہیں۔

ٹیم چاہتی تھی کہ ہر موک کو کمپوننٹ ٹری سے باہر نکالا جائے، فرنٹ اینڈ اور بیک اینڈ کے درمیان ایک معاہدہ (contract) نافذ کیا جائے، اور اس بات کی ضمانت دی جائے کہ پروڈکشن بلڈ میں کوئی اضافی چیز شامل نہ ہو۔

وہ تین مرحلہ وار عمل جس پر ٹیم عمل کرتی ہے

  1. Contract meeting – فرنٹ اینڈ اور بیک اینڈ انجینئرز مل بیٹھتے ہیں اور ہر ریکویسٹ، اس کے URL، میتھڈ (method) اور متوقع پے لوڈ (payload) کی فہرست بناتے ہیں۔
  2. Typed contract – وہ اس فہرست کو ایک TypeScript interface میں تبدیل کر دیتے ہیں جو ریکویسٹ اور رسپانس کی شکلوں (shapes) کے لیے واحد مستند ذریعہ (single source of truth) بن جاتا ہے۔
  3. Interceptor wiring – ایک Axios interceptor ہر جانے والی ریکویسٹ کا معائنہ کرتا ہے۔ اگر URL کسی رجسٹرڈ موک سے میچ کرتا ہے، تو انٹرسیپٹر موک ڈیٹا واپس کر دیتا ہے؛ ورنہ ریکویسٹ لائیو سرور پر چلی جاتی ہے۔

چونکہ انٹرسیپٹر ہی وہ واحد جگہ ہے جہاں موک لاجک موجود ہوتی ہے، اس لیے کمپوننٹ کوڈ تبدیل نہیں ہوتا۔ ڈویلپرز بغیر کسی کنڈیشنل لاجک (conditional logic) کے اپنے معمول کے ڈیٹا فیچنگ ہکس—جیسے useQuery—کا استعمال جاری رکھتے ہیں۔

پروڈکشن بلوٹ (production bloat) سے کیسے بچا جاتا ہے

ٹیم نے تین حفاظتی اقدامات (safeguards) کا استعمال کیا ہے جو Rollup (Vite کے ذریعے استعمال ہونے والا بنڈلر) کو پروڈکشن کے لیے بلڈ بناتے وقت موک کوڈ کو مکمل طور پر ہٹانے کی اجازت دیتے ہیں:

  • پروڈکشن بلڈ میں import.meta.env.DEV کا نتیجہ false نکلتا ہے، اس لیے tree-shaking کے دوران پورا انٹرسیپٹر ماڈیول غائب ہو جاتا ہے۔
  • یونٹ ٹیسٹ چلاتے وقت MODE ویری ایبل کو test کے علاوہ کسی اور چیز پر سیٹ کیا جاتا ہے، جس سے صرف ٹیسٹ کے لیے استعمال ہونے والا کوڈ الگ رہتا ہے۔
  • ایک کسٹم فلیگ، VITE_ENABLE_MSW، ڈیفالٹ طور پر false ہوتا ہے اور موک کو فعال کرنے کے لیے اسے واضح طور پر آن کرنا پڑتا ہے۔

جب یہ تینوں شرائط غلط (false) ہوں، تو موک رجسٹری کبھی بھی فائنل بنڈل کا حصہ نہیں بنتی۔

موک فائلوں کی تنظیم

ریپوزٹری (repo) فیچر پر مبنی لے آؤٹ پر عمل کرتی ہے:

  • interfaces/ – اس میں کنٹریکٹ میٹنگ سے تیار کردہ TypeScript تعریفیں (definitions) ہوتی ہیں۔
  • scenarios.ts – اس میں ہر اینڈ پوائنٹ کے لیے کامیاب رسپانسز اور ایرر کیسز کی ٹھوس مثالیں ہوتی ہیں۔
  • devHandlers.ts – یہ ایک مرکزی رجسٹری کے طور پر کام کرتا ہے جو URLs کو سیناریو ڈیٹا سے جوڑتا ہے اور انٹرسیپٹر کو Axios میں لگا دیتا ہے۔

ایک چھوٹا اسکیفولڈنگ اسکرپٹ (scaffolding script) ان فائلوں کو خودکار طور پر تیار کر سکتا ہے: اسے ایک URL اور متعلقہ انٹرفیس دیں، اور یہ اسٹب فائلیں (stub files) بنا دے گا اور موک کو رجسٹر کر دے گا۔ یہ اسکرپٹ پروڈکشن کوڈ کے راستے سے باہر ہوتا ہے، اس لیے یہ بنڈل کے سائز پر اثر انداز نہیں ہوتا۔

ٹیم کو کیا حاصل ہوا

  • کمپوننٹس کے اندر زیرو موکس – تمام جعلی ڈیٹا ایک مخصوص لیئر میں ہوتا ہے، جس سے UI کوڈ صاف ستھرا رہتا ہے۔
  • اینڈ ٹو اینڈ ٹائپ سیفٹی – موک ڈیٹا انہی TypeScript interfaces کے مطابق ہوتا ہے جو اصل رسپانسز کے لیے استعمال ہوتے ہیں، اس لیے غلطیوں کا پتہ کمپائل ٹائم پر ہی چل جاتا ہے۔
  • پروڈکشن میں کوئی اضافی بوجھ نہیں – Tree-shaking انٹرسیپٹر اور موک ڈیٹا کو مکمل طور پر ہٹا دیتی ہے، جس سے بنڈل کا سائز تبدیل نہیں ہوتا۔
  • ڈویلپمنٹ اور ٹیسٹ کے لیے مشترکہ سیناریوز – وہی موک تعریفیں لوکل ڈویلپمنٹ اور خودکار ٹیسٹ دونوں کو چلاتی ہیں، جس سے تکرار (duplication) کم ہوتی ہے۔

سمجھوتہ اور حدود

یہ طریقہ کار اصل بیک اینڈ کا متبادل نہیں ہے۔ اگر موک کنٹریکٹ لائیو API سے مختلف ہو جائے، تو ڈویلپرز کو اس فرق کا پتہ صرف اس وقت چلتا ہے جب وہ انوائرمنٹ فلیگ تبدیل کرتے ہیں۔

آگے کیا دیکھنا ہے

  • ٹولنگ انٹیگریشن
  • وسیع تر اپناؤ
  • پرفارمنس مانیٹرنگ

حاصلِ کلام واضح ہے: موک لاجک کو ایک ٹائپڈ اور انوائرمنٹ کے ذریعے کنٹرول شدہ لیئر میں منتقل کرنے سے فرنٹ اینڈ ٹیمیں اپنے کمپوننٹس کو خالص رکھ سکتی ہیں، ٹائپ سیفٹی برقرار رکھ سکتی ہیں، اور چھپے ہوئے موک پے لوڈز کے بغیر پروڈکشن بلڈز جاری کر سکتی ہیں۔ ایک مشترکہ کنٹریکٹ کو برقرار رکھنا ایک ہموار ڈویلپمنٹ ورک فلو اور صاف ستھرے کوڈ بیس کی قیمت ہے۔