צוות frontend הטמיע שכבת API-mocking מבוססת טיפוסים (type-safe) שקיימת רק בסביבת הפיתוח. באמצעות Axios interceptors ו-tree-shaking של Vite, ה-bundle של הייצור (production) נשאר ללא שינוי. מהנדסים שולפים נתונים בתבניות הרגילות שלהם בזמן שהם ממתינים לנקודות קצה (endpoints) של ה-backend, ואז מחליפים דגל סביבה (environment flag) בודד כדי לפנות ל-API האמיתי.

למה הצוות היה זקוק לדרך טובה יותר לביצוע Mocking

מפתחי frontend נתקלים במחסום כאשר נתיב (route) ב-backend אינו מוכן. הפתרון המהיר — hard-coding של תגובה בתוך קומפוננטה או פיזור בלוקים של if (process.env.NODE_ENV === 'development') ברחבי ה-UI — מאפשר לאפליקציה להמשיך להתקדם, אך משאיר חוב טכני (technical debt). אובייקטי ה-mock הללו הופכים לחלק מהלוגיקה של הקומפוננטה, מעלים את הסיכון לשליחת נתונים מזויפים לייצור (production), ומקשים על קריאת הקוד ובדיקתו.

הצוות רצה להוציא כל mock מחוץ לעץ הקומפוננטות, לאכוף חוזה (contract) בין ה-frontend ל-backend, ולהבטיח ששום דבר מיותר לא יגיע ל-build של הייצור.

תהליך שלושת השלבים שהצוות עוקב אחריו

  1. פגישת חוזה (Contract meeting) – מהנדסי ה-frontend וה-backend מתיישבים ומרשימים כל בקשה, ה-URL שלה, המתודה (method) וה-payload הצפוי.
  2. חוזה מבוסס טיפוסים (Typed contract) – הם הופכים את הרשימה ל-TypeScript interface שהופך למקור האמת היחיד (single source of truth) עבור מבני הבקשות והתגובות.
  3. חיבור ה-Interceptor – Axios interceptor בודק כל בקשה יוצאת. אם ה-URL תואם ל-mock רשום, ה-interceptor מחזיר את נתוני ה-mock; אחרת, הבקשה ממשיכה לשרת החי.

מכיוון שה-interceptor הוא המקום היחיד שבו קיימת לוגיקת ה-mock, קוד הקומפוננטות נשאר ללא שינוי. מפתחים ממשיכים להשתמש ב-hooks הרגילים שלהם לשליפת נתונים — כגון useQuery — מבלי להוסיף לוגיקה מותנית כלשהי.

איך נמנעת התנפחות (bloat) בגרסת הייצור

הצוות הטמיע שלוש שכבות הגנה המאפשרות ל-Rollup (ה-bundler שבו משתמשים ב-Vite) להסיר לחלוטין את קוד ה-mock בעת בנייה לייצור:

  • import.meta.env.DEV נפתר ל-false ב-build של ייצור, כך שכל מודול ה-interceptor נעלם במהלך ה-tree-shaking.
  • משתנה ה-MODE מוגדר למשהו שאינו test בעת הרצת unit tests, מה ששומר על קוד המיועד לבדיקות בנפרד.
  • דגל מותאם אישית, VITE_ENABLE_MSW, מוגדר כברירת מחדל ל-false ויש להפעילו במפורש כדי להפעיל את ה-mock.

כאשר שלושת התנאים הללו הם false, רישום ה-mock לעולם לא מגיע ל-bundle הסופי.

ארגון קבצי ה-mock

המאגר (repo) עוקב אחר מבנה מבוסס פיצ'רים (feature-centric):

  • interfaces/ – מחזיק את הגדרות ה-TypeScript שנוצרו מפגישת החוזה.
  • scenarios.ts – מכיל דוגמאות קונקרטיות לתגובות מוצלחות ומקרי שגיאה עבור כל endpoint.
  • devHandlers.ts – משמש כרישום המרכזי שממפה URLs לנתוני ה-scenario ומחבר את ה-interceptor ל-Axios.

סקריפט scaffolding קטן יכול לייצר את הקבצים הללו באופן אוטומטי: נותנים לו URL ו-interface תואם, והוא יוצר את קבצי ה-stub ורושם את ה-mock. הסקריפט נמצא מחוץ לנתיב הקוד של הייצור, כך שהוא אינו משפיע על גודל ה-bundle.

מה הצוות הרוויח

  • אפס mocks בתוך קומפוננטות – כל הנתונים המזויפים חיים בשכבה ייעודית, מה ששומר על קוד ה-UI נקי.
  • Type safety מקצה לקצה – נתוני ה-mock תואמים לאותם ממשקי TypeScript המשמשים לתגובות אמיתיות, כך שחוסר התאמה נתפס בזמן הקומפילציה.
  • ללא משקל בייצור – ה-tree-shaking מסיר את ה-interceptor ואת נתוני ה-mock לחלוטין, מה שמשאיר את גודל ה-bundle ללא שינוי.
  • תרחישים (scenarios) משותפים לפיתוח ולבדיקות – אותן הגדרות mock מניעות הן את הפיתוח המקומי והן בדיקות אוטומטיות, מה שמפחית כפילות.

הפשרות והמגבלות

הגישה אינה מחליפה backend אמיתי. אם חוזה ה-mock חורג מה-API החי, המפתחים יגלו את חוסר ההתאמה רק לאחר שיחליפו את דגל הסביבה.

מה לעקוב אחריו בהמשך

  • אינטגרציה של כלי עבודה (Tooling integration)
  • אימוץ רחב יותר
  • ניטור ביצועים

השורה התחתונה ברורה: העברת לוגיקת ה-mock לשכבה מבוססת טיפוסים ומוגנת סביבה מאפשרת לצוותי frontend לשמור על קומפוננטות נקיות, לשמור על type-safety, ולהוציא builds לייצור ללא עומס נתונים נסתר של mocks. שמירה על חוזה משותף היא המחיר של זרימת עבודה (workflow) חלקה יותר וקוד נקי יותר.