מדוע Web Components נשברים כשמטמיעים אותם בממשק של מישהו אחר
קומפוננטה שנראית ללא רבב בחלון תצוגה מבודד, נוחתת בממשק קיים ומתפרקת: כותרות מתנגשות, הכפתור מאבד ריווחים, חלון המודאל עובר מתחת לשכבה של מישהו אחר.
Shadow DOM מבודד חוקים, אך אינו מבטל ירושה: איפוסים גלובליים וטיפוגרפיה של המארח מגיעים עד לתוכן ה-slot, ודרך משתני CSS חודרת פנימה ערכת הנושא של האפליקציה.
בידוד הסגנונות של הקומפוננטה מתגלה כהסכם, ולא כהבטחה. שינו את שם הטוקן במארח — הקומפוננטה נצבעה מחדש בשקט; שינו את אופן טעינת הגופן — הגריד זז. קונפליקטים כאלה של סגנונות כמעט ואינם נראים בעמוד דמו: הם צפים על נתונים אמיתיים, בערכת נושא כהה ובשורות ארוכות.
לאחר מכן מצטרפים ה-state והבנייה. פריימוורקים מעבירים נתונים בדרכים שונות — דרך מאפיין מחרוזתי, פרופרטי או עדכון ריאקטיבי — וחלק מהשינויים בתוך הקומפוננטה נשארים בלתי נראים למארח. אירוע מצומת מקונן מגיע כאירוע של הקומפוננטה עצמה, והמטפלים פועלים במקום שלא מצפים להם. שתי גרסאות של אותה ערכה בבנייה יוצרות משקל מיותר ומחלוקת על מי מהתגים נרשם ראשון.
עניין בפני עצמו הוא שכפול הלוגיקה: ולידציה של טפסים, לוקליזציה, עיצוב תאריכים ותמטיזציה מתפשטים בין האפליקציה לקומפוננטות, כי אין להן חוזה משותף. בהמשך נבחן כיצד זה נסגר ברמת הטוקנים, הגבולות והבדיקות בעת ההטמעה.
מה נותנת ערכת קומפוננטות אחודה על פני סטאקים שונים
הקומפוננטה מוגדרת פעם אחת לפי תקן האינטרנט Custom Elements ומחוברת כתג רגיל ב-React, Vue ו-Angular — ללא עטיפות לכל פריימוורק. בפנים פועל DOM צל: הסגנונות והמארקאפ מבודדים, ולכן חוק ממערכת העיצוב אינו נדרס על ידי הקסקדה של האפליקציה.
מעל התקן נוח לקחת Lit: תבניות דקלרטיביות ופרופרטיז ריאקטיביים מסלקים עבודה ידנית עם מחזור החיים של האלמנט.
מקור אמת אחוד משנה את הכלכלה של העריכות. בעבר כפתור, שדה או טבלה חיו בשלושה ריפוזיטוריז והתפצלו כבר בשיפור הראשון; כעת השינוי מוכנס פעם אחת ומגיע לכל הממשקים בריליז אחד. קוד משוכפל מצטמצם בשליש ויותר, והתיקון עצמו יוצא באותו יום, ולא כשלוש משימות במקביל.
גם חוזה האינטראקציה נעשה אחוד: הפרופרטיז והאירועים מוגדרים פעם אחת, ולא נכתבים מחדש לפי הפרופס של כל פריימוורק. בדיקות ההתנהגות נכתבות מול התקן ואינן משוכפלות לשלוש פלטפורמות — ערכת בדיקות אחת מכסה את כל האפליקציות.
מכאן גם הצפיות: מצב זהה של הקומפוננטה נראה ומתנהג באופן זהה בפאנל הניהול, באזור האישי של הלקוח ובלנדינג.
עלות התחזוקה של הממשקים יורדת לא באמצעות צמצום, אלא באמצעות סילול אי-ההתאמות: פחות ענפי קוד, פחות "ייחודים" של פריימוורק מסוים, סדר אחד של עדכון תלויות. נבחן כיצד שכבה כזו מוטמעת באפליקציות קיימות ללא כתיבה מחדש.
דרכי אריזה ואספקה של קומפוננטות: השוואה
אופן האספקה קובע כמה עבודה תיפול על הצוותים בכל עדכון של ערכת הקומפוננטות. את אותו קוד אפשר לספק כחבילה מוכנה, כעטיפה מיוצרת לסטאק מסוים או כקוד מקור בריפוזיטורי משותף — ומחיר התחזוקה במקרים אלה שונה.
להלן האפשרויות שבין אהן באמת בוחרים, עם המגבלות שמתגלות לא בדמו, אלא בריליז השלישי-רביעי.
| אפשרות | מתי מתאימה | מגבלות |
|---|---|---|
| חבילת קומפוננטות מוכנה | ערכה אחודה במספר אפליקציות, עדכון ממורכז | ערכות נושא מוגדרות דרך פרופרטיז מותאמים; רינדור בצד השרת דורש תמיכה נפרדת |
| עטיפה לסטאק | צוותים רוצים סינטקס מוכר, טיפוסים והשלמה אוטומטית | את העטיפה בונים מחדש בכל גרסת מאז'ור; חלק מהאירועים וה-slots מועברים ידנית |
| חיבור ישיר של הבנדל לעמוד | הטמעה בעמודים על סטאק ישן, מערכות תוכן, לנדינגים | הגרסאות בעמודים מתפצלות, אין שליטה בתלויות — התאימות נשמרת ידנית |
| קוד מקור בריפוזיטורי משותף | יש צורך בפורקים ובעריכות לעצמך | העדכונים אינם מגיעים מעצמם; ניהול גרסאות ורגרסיה — באחריות הצוות |
כיצד שומרים על תאימות לאחור
גירסור הקומפוננטות נקשר לחוזה, ולא לפנים: פרופרטיז, אירועים, slots. גרסת המאז'ור משתנה רק עם מחיקה או שינוי משמעות של מאפיין, והשאר עובר כמינור. השמות הישנים ממשיכים לעבוד עוד מחזור מאז'ור אחד, ולכן עדכון הספרייה בשירות אחד אינו מחייב ריליז מסונכרן של השכנים.
כיצד אנו מטמיעים ספריית קומפוננטות: שלבי העבודה
הטמעת ספרייה מבוססת web components מתחילה לא בקוד, אלא במיפוי מלאי של ממשקי הפרודקשן. כל עוד אין מפה של האלמנטים הקיימים והפערים ביניהם, הערכת לוחות הזמנים חסרת ערך. אנו צועדים ברצף קבוע — מהאודיט ועד למסירה לצוות.
- אודיט הממשק. אוספים רשימה של מסכים ומנתחים את האלמנטים הקיימים לפי תדירות השימוש, פערים במארקאפ, מצבים והתנהגות.
- סכמת הקומפוננטות. מקבעים את הגבולות של כל אלמנט: מה עובר לערכה האחודה, מה נשאר מקומי, אילו פרופרטיז ואירועים נעשים לממשק הפומבי.
- אב-טיפוס במפגש בין פריימוורקים. בונים קומפוננטה אחת או שתיים ומחברים אותן ב-React, Vue ו-Angular — בודקים שאירועים, slots וסגנונות מתנהגים בצורה צפויה בכל אחד.
- מימוש הספרייה. כותבים ערכה מתואמת, מכסים מצבים, נגישות וערכת עיצוב, מגדירים גירסור ופרסום של חבילה פנימית.
- הגירת מסכים. מחליפים את המימושים הישנים בהדרגה, מסלול אחד לריליז, עם אפשרות לחזור לגרסה קודמת של הממשק.
- קבלת התוצאה. מריצים בדיקות התנהגות ויזואליות, משווים למוקאפים, מתעדים את שיעור התרחישים המכוסים ואת רשימת החריגים המודעים.
- מסירה לצוות. מוסרים את הריפוזיטורי, התיעוד, כללי הריליז ועדכון התלויות, ועוברים על המבנה בקוד חי.
בכל שלב יש תוצר מוחשי: אחרי האודיט — מפת אלמנטים, אחרי האב-טיפוס — קומפוננטה שעובדת באופן זהה בכל הפריימוורקים, אחרי המסירה — צוות שמפתח את הספרייה בעצמו.
מה נשאר בפרויקט: ריפוזיטורי, סכמות, נהלים
אנו מוסרים את הפרויקט כך שהצוות של הלקוח יוכל לפתח אותו ללא מעורבותנו. מסירה אינה ארכיון עם בילד, אלא ערכת ארטיפקטים, שכל אחד מהם עונה על שאלה משלו: מה לשנות, היכן הגבולות, במה לבדוק את התוצאה. להלן הרכב החבילה שעוברת לצד הלקוח.
- קוד המקור של הקומפוננטות. ריפוזיטורי עם חבילות: הווב-קומפוננטות עצמן, סגנונות משותפים וטוקנים של ערכת נושא, עטיפות דקות לפריימוורקים הצורכים. הבילד משוחזר בפקודה אחת על מכונה נקייה.
- תיעוד הספרייה. תיאור פומבי של ה-API של כל קומפוננטה: פרופרטיז, אירועים, slots, מצבי טעינה ושגיאה. בנוסף דוגמאות שימוש וחלון תצוגה עם כל וריאציות העיצוב.
- סכמת התלויות. גרף של "מה תלוי במה": היכן החבילות החיצוניות, אילו גרסאות תואמות ביניהן ומה יקרה בעדכון שלהן למעלה.
- נוהל העדכונים. כללי הוצאת גרסאות: מה נחשב לשינוי שובר, כיצד מועלה המינור, כיצד הצרכנים נודעים על גרסה חדשה ובאיזה מועד עוברים אליה.
- כללי ביצוע שינויים. הסכמה לגבי ענפים ומתן שמות למשימות, בדיקות חובה לפני מיזוג, דרישות לסקירת קוד ולבדיקות ללוגיקה חדשה.
- ערכת בדיקות. רגרסיה לפי קומפוננטות, השוואות ויזואליות של הרינדור, בדיקת התאמת החוזים בין הקומפוננטה לעטיפות שלה, והרצת כל זה בכל שינוי.
- הוראות הרצה והוצאה לאור. מסמך צעד-אחר-צעד: להקים סביבה, לבנות, לדבג, להוציא ריליז. כתוב עבור מהנדס חדש, ולא עבור מחבר הקוד.
חבילה כזו סוגרת את הסיכון המרכזי של המסירה: הלקוח רואה היכן נגמרת העבודה שלנו ומתחילה אחריותו. את התיקון העצמאי הראשון הצוות מבצע בנוכחותנו, בשני כבר אין בנו צורך.
מקרה בוחן: כיצד סולק שיכפול הממשקים בארבעה מוצרים
ארבעה מוצרים של חברה אחת — אזור הלקוח, פאנל הניהול, פורטל פומבי וגרסת ווב לנייד — התפתחו על ידי צוותים שונים ועם הזמן התפצלו בפרטים. הבלוקים המרכזיים של הממשק — טבלאות עם מיון והוצאה מדורגת, מסננים, טפסים, בחירת תאריך, העלאת קבצים — התקיימו ב-9–14 עותקים כל אחד.
נקודת הפתיחה
העותקים חיו חיים משלהם: בטבלה אחת ניווט המקלדת עבד, בשנייה — לא, המסנן בפאנל המפעיל אופס אחרת מאשר באזור הלקוח, ובדיקת השדות נבדלה בכללים.
תיקון של התנהגות אחת דרש עבודה מסונכרנת בארבעה ריפוזיטוריז, והפער צף כבר בשלב הקבלה — שיעור הליקויים בממשק שהתגלו לאחר ההוצאה לאור נשמר בסביבות שליש.
מה עשינו
את הבלוקים המשותפים ריכזנו בשכבה אחודה על Web Components: הקומפוננטה נבנית ונבדקת פעם אחת, וב-React, Vue ו-Angular מחוברת כאלמנט רגיל — ללא עותקים של מארקאפ, סגנונות ולוגיקת ולידציה.
הסגנונות, ההתנהגות וערכות הבדיקות יושבים בריפוזיטורי אחד עם גרסה אחת ויומן שינויים אחד, ולכן מוצר אחד כבר אינו יכול לפגר אחרי האחרים בהתנהגות הבלוק.
| מדד | לפני | אחרי |
|---|---|---|
| עותקים של בלוק אחד | 9–14 | 1 |
| ריפוזיטוריז לתיקון אחד | 4 | 1 |
| ערכת בדיקות לבלוק | נפרדת בכל מוצר | משותפת |
| ליקויי ממשק לאחר ההוצאה לאור | כשליש | בודדים |
עברנו בהדרגה: מסכים חדשים נבנו מיד מהשכבה האחודה, עותקים ישנים הוחלפו ככל שהתבצעו שיפורים מתוכננים, ולכן לא היה צורך לכתוב את המוצרים מחדש בשלמותם. הזמן לשיפור של בלוק אופייני הצטמצם פי כמה, והחזרה לגרסה קודמת של הקומפוננטה נעשית כעת בפעולה אחת עבור כל המוצרים בבת אחת.
במה Web Components נבדלות מספריית ממשקים רגילה
ספריית ממשקים היא הסכמה בתוך סטאק אחד: הקומפוננטות חיות במודל הרינדור של פריימוורק מסוים ונבנות בכלים שלו. כל עוד יש מוצר אחד וסטאק אחד, שאלת הניידות אינה עולה. הגבול ניכר כשאותה קומפוננטה דרושה באפליקציה אחרת או בפריימוורק זר.
Web Components מעבירות את ההסכמות לרמה של פלטפורמת הווב. אלמנט מותאם הוא תג רגיל במארקאפ, והמבנה הפנימי סגור על ידי עץ צל: סגנונות חיצוניים אינם מחלחלים פנימה, הפנימיים אינם משפיעים על העמוד. את בידוד המארקאפ מספק הדפדפן, ולא הסכמות ולינטרים.
מכאן גם ההבדל בתלות בסטאק. הספרייה גוררת אחריה את סביבת ההרצה של הפריימוורק, ואין להטמיע את הקומפוננטה שלה באפליקציה זרה ללא בנייה מחדש. אלמנט מותאם מחובר באימפורט ועובד בכל סביבה שיש בה DOM של דפדפן.
בחירת הגישה אינה עניין של "מודרניות", אלא של היכן עובר הגבול בין המוצרים. אם הוא בתוך צוות אחד וסטאק אחד, הספרייה מספיקה. אם הקומפוננטות חוצות גבולות של אפליקציות, הגיוני לעשות את הבידוד ברמת הפלטפורמה.
ספקות טכניים נפוצים לפני תחילת הפרויקט
הספקות לפני ההתחלה נוגעים לא לתקן עצמו — הוא יציב ומתועד — אלא למפגשים: כיצד להטמיע אלמנטים בפרויקט חי, מי יתחזק אותם, מה לעשות עם דפדפנים ישנים וכיצד להוציא עדכונים מבלי לשבור מודולים שכנים. להלן תשובות הנדסיות למה ששואלים לרוב במפגשים טכניים.
האם אפשר להטמיע בפרויקט פעיל ללא כתיבה מחדש?
כן. הקומפוננטות מחוברות כתגים רגילים ואינן דורשות החלפת מערכת הבנייה: React, Vue ו-Angular ממשיכים לעבוד כבעבר, והאלמנטים המשותפים חיים במקום אחד. מתחילים מבלוק אחד — ההדר או ווידג'ט התשלום — ומעבירים את השאר לפי הצורך. אין צורך לכתוב את כל הממשק מחדש בבת אחת.
האם נוכל לתחזק את זה בכוחות עצמנו?
כן, אם נמסור קוד, בדיקות ותיעוד של חוזי האלמנטים: אילו מאפיינים הקומפוננטה מקבלת, אילו אירועים היא מפיקה, מה נחשב לשינוי שובר. אין צורך בידע מעבר לפלטפורמת הדפדפן. את המסירה אנו עורכים על קוד חי, כדי שהמפתח שלכם יבצע תיקונים בעצמו מיד.
מה עם דפדפנים ישנים ותצוגות מוטמעות?
היכולות המרכזיות של התקן נתמכות בכל הדפדפנים העכשוויים, כולל ניידים. לגרסאות מיושנות אנו מוסיפים שכבת תאימות ומתכננים דגרדציה: אם האלמנט לא עלה, המשתמש רואה מארקאפ בעל משמעות, ולא שטח ריק. אנו בודקים על מכשירים אמיתיים, ולא רק באמולטור.
כיצד לעדכן קומפוננטות מבלי לשבור מודולים זרים?
כל אלמנט מנוהל בגרסה נפרדת ומפורסם כחבילה עצמאית, ולכן עדכון של בלוק אחד אינו גורר אחריו את האחרים. את החוזה — מאפיינים, אירועים, slots — מקבעים ומשנים רק בגרסת מאז'ור, ולפני ההוצאה לאור מריצים בדיקות תאימות. צוותים שכנים עוברים לגרסה החדשה כשהם מוכנים.
נדון במשימה ונחזור עם הערכה ותוכנית עבודה
כדי לחזור עם הערכת היקף העבודה ותוכנית ההטמעה, אין אנו זקוקים לניתוח טכני מלא — די בכמה נתוני פתיחה, ואת השאר יאספו המהנדסים בעצמם בשיחה עם הצוות שלכם. ככל שנתוני הפתיחה מדויקים יותר, כך פחות הנחות בלוחות הזמנים של השלבים ובהרכב הצוות.
מה כדאי לצרף לתיאור המשימה:
- רשימה של פריימוורקים והענפים העכשוויים שלהם באפליקציות שלכם — מכך תלוי כמה אדפטרים ועטיפות ייכנסו לתוכנית ההטמעה.
- רשימה של בלוקי ממשק שצריכים להפוך למשותפים: טפסים, טבלאות, מסננים, התראות, ווידג'טים.
- קישור לריפוזיטורי או ייצוא של מבנה הפרויקט — כך נעריך את קו הבנייה ואת נקודות האינטגרציה ללא ניחושים.
- דרישות לתמטיזציה: ערכות נושא בהירות וכהות, מיתוג, נגישות וניווט מקלדת.
- מגבלות על דפדפנים וסביבות, כולל גרסאות מיושנות שעדיין בפרודקשן.
- הרכב הצוות שלכם ותחומי האחריות: מי מאשר את הארכיטקטורה, מי בודק את השינויים, מי אחראי על הריליז.
- לוחות זמנים צפויים לשלבים ותאריכים קשיחים — קישור לריליז או להגירה משנה את סדר העבודות.
לאחר שיחה קצרה נקבע את הערכת היקף העבודה, הרכב הצוות ולוחות הזמנים של השלבים. את תוכנית ההטמעה נחלק לצעדים עצמאיים, כדי שניתן יהיה לחבר את ספריית ה-web components הראשונה המשותפת מבלי להמתין להעברת כל האפליקציות.
תארו את המשימה — נחזור עם הערכה ותוכנית.







