→ כל החידושים
|החלטות ארכיטקטורה באתר הזה

build שנכשל הוא פיצ'ר — ולידציית תוכן עם zod לפני שהבאג מגיע ללקוח

architecturetypescript

כמה מושגים בעברית פשוטה לפני שצוללים: build הוא התהליך שהופך את קוד המקור לאתר מוכן להגשה — מריצים פקודה, והכלים מקמפלים, בודקים ואורזים הכול. ולידציה היא בדיקת תקינות של נתונים: "האם מה שקיבלתי הוא באמת מה שציפיתי לקבל?". ו-frontmatter הוא בלוק המידע הקטן שבראש קובץ תוכן (בין שני קווי ---): כותרת, תאריך, תגיות.

עכשיו לעיקרון ששווה להכיר בשמו: Shift Left. אם מציירים את חיי הקוד כציר זמן משמאל לימין — כתיבה, build, פרודקשן — אז ככל שתופסים שגיאה שמאלה יותר, היא זולה יותר. שגיאה בזמן כתיבה עולה שניות; ב-build — דקות; בפרודקשן מול לקוח — אמון.

באתר הזה התוכן של "חידוש יומי" חי בקבצי Markdown. מה קורה אם אכתוב תאריך בפורמט שגוי או אשכח כותרת? בלי הגנה — העמוד יתרנדר שבור בשקט, ואף אחד לא יצעק.

הפתרון: סכמה של zod — ספרייה שמגדירה "איך נתונים תקינים אמורים להיראות" ובודקת כל קובץ מולה בזמן ה-build:

const frontmatterSchema = z.object({
  title: z.string().min(3, "כותרת קצרה מדי"),
  date: z.string().regex(/^\d{4}-\d{2}-\d{2}$/, "תאריך חייב להיות YYYY-MM-DD"),
  tags: z.array(z.string()).min(1).max(5),
});

const parsed = frontmatterSchema.safeParse(data);
if (!parsed.success) {
  throw new Error(`Frontmatter לא תקין ב-${file}: ...`);
}

עכשיו קובץ פסול מפיל את ה-build עם הודעה שמצביעה על הקובץ והשדה המדויקים. בדקתי בכוונה — שברתי תאריך, וה-build נעצר עם בדיוק השורה שצריך לתקן. זה הרגע שבו build שנכשל הוא לא תקלה אלא רשת ביטחון.

הנקודה הרחבה: באתר סטטי ה-build הוא שער האיכות האחרון לפני הגולשים, אז שווה להפוך אותו לקשוח. והעיקרון תקף לכל מערכת — ולידציה של קלט בכניסה ל-API ולא עמוק בלוגיקה, טיפוסים קשוחים בגבולות המערכת. זו אותה משפחה של עקרון ההרשאה המינימלית שפגשנו בכותרות האבטחה: כללים קטנים, מוצהרים מראש, שסוגרים דלתות לפני שמישהו מנסה לפתוח אותן.