תאימות בסביבה העסקית של JavaScript framework
בפוסט של המבוא בבלוג, סיפרנו איך למדנו הרבה תוך כדי פיתוח מסגרות וכלים, במטרה לפתח ולתחזק אפליקציות אינטרנט בקנה מידה גדול כמו חיפוש Google, מפות Google, Photos ועוד. בזכות ההגנה על המפתחים מפני כתיבת קוד שיכול להשפיע לרעה על חוויית המשתמש, הוכיחנו של-frameworks יש תפקיד מרכזי בשינוי התוצאות של הביצועים ושל איכות האפליקציות.
השתמשנו במונח "תאימות" באופן פנימי ב-Google כדי לתאר את המתודולוגיה הזו, והמאמר הזה מסביר איך אנחנו מתכננים להוסיף את הקונספט הזה לקוד פתוח בסביבה העסקית של מסגרת JavaScript.
מהי תאימות?
ההגדרה של תאימות ב-Google הייתה התפתחות. הצוותים הסתמכו על קבוצה קטנה של אנשי תחזוקה מנוסים שערכו בדיקות קוד מקיפות וסימנו דברים שהשפיעו על איכות האפליקציה ועל התחזוקה הרבה מעבר לבעיות התקינות. כדי להתאים את השימוש לצוותים גדלים והולכים של מפתחי אפליקציות, פיתחנו מערכת תאימות כדי לקודד את השיטות המומלצות באופן אוטומטי ונאכף. כך אפשר להבטיח רף גבוה באופן עקבי לאיכות האפליקציה ולשמירה על בסיס הקוד, ללא קשר למספר האנשים שתורמים לקוד.
תאימות היא מערכת שמבטיחה שהמפתחים יישארו בנתיב מואר היטב – היא יוצרת ביטחון ומבטיחה תוצאות ניתנות לחיזוי. כך הצוותים יהיו פרודוקטיביים וחיוניים להתאמה לעומס (scaling) – ככל שהצוותים גדלים ומפתחים בו-זמנית תכונות נוספות. היא עוזרת למפתחים להתמקד בבניית תכונות של מוצרים, וכך לשחרר אותם מאלמנטים קטנים ומהסביבה המשתנה בתחומים שונים כמו ביצועים, נגישות, אבטחה וכו'. כל אחד יכול להפסיק את התאימות בכל שלב, ובמידה שלצוותים תהיה אפשרות לאכוף כל פעולה שהם יחליטו להתחייב אליה.
תאימות מבוססת על הגדרות ברירת מחדל חזקות ומספקת כללים שניתן לפעול לפיהם שאפשר לאכוף בזמן כתיבת התוכן. המידע הזה מתחלק ל-3 העקרונות הבאים.
1. ברירות מחדל חזקות
אחד ההיבטים הבסיסיים של תאימות הוא לוודא שלכלים שבהם המפתחים משתמשים יש הגדרות ברירת מחדל חזקות. כלומר, לא רק פתרונות מוטמעים במסגרות, אלא גם דפוסי עיצוב של framework כדי שיהיה קל לעשות את הדבר הנכון וקשה לפעול לפי דפוסים מנוגדים. ה-framework תומך במפתחים עם עיצוב אפליקציות ומבנה קוד.
כדי לטעון את הביצועים, יש לבצע אופטימיזציה לכל משאב (גופנים, CSS, JavaScript, תמונות וכו'). זהו אתגר מורכב שכולל חיתוך בייטים, צמצום הנסיעות הלוך ושוב והפרדה בין מה שנדרש לעיבוד הראשון, למוכנות חזותית ולאינטראקציה של המשתמש. לדוגמה, חילוץ CSS קריטי והגדרת עדיפות לתמונות חשובות.
2. כללים שאפשר לפעול לפיהם
גם אם מתבצעים אופטימיזציות בסיסיות, מפתחים עדיין צריכים לקבל החלטות. יש מגוון רחב של אפשרויות לאופטימיזציה כשמדובר בכמות שנדרשת מהמפתחים:
- ברירות מחדל שלא מחייבות קלט של מפתח, כגון הטבעה של CSS קריטי.
- נדרשת הצטרפות של המפתח. לדוגמה, אפשר להשתמש ברכיב תמונה שסופק על ידי framework כדי לשנות את הגודל ואת הגודל של התמונות.
- נדרשת הצטרפות והתאמה אישית של המפתח. לדוגמה, תיוג תמונות חשובות שייטען לפני הזמן.
- לא תכונה ספציפית אלא דברים שעדיין מחייבים החלטה של המפתח. לדוגמה, כדאי להימנע מגופנים או מסקריפטים סינכרוניים שמעכבים את העיבוד בשלב מוקדם.
פעולות אופטימיזציה שמחייבות החלטה של המפתחים עלולות לסכן את ביצועי האפליקציה. ככל שנוסיף עוד תכונות והצוות שלכם יתאים לעומס, גם המפתחים המנוסים ביותר לא יכולים להתעדכן בשיטות המומלצות שמשתנות כל הזמן, וגם לא מנצלים את הזמן שלהם בצורה הטובה ביותר. כדי לשמור על תאימות, כללים מתאימים לפעולות חשובים באותה מידה כמו ברירות מחדל חזקים כדי להבטיח שהאפליקציה תמשיך לעמוד בסטנדרט מסוים גם כשהמפתחים ממשיכים לבצע שינויים.
3. זמן היצירה
חשוב לזהות ולמנוע בעיות ביצועים בשלב מוקדם במחזור החיים של הפיתוח. זמן היצירה, לפני יצירת הקוד, מתאים במיוחד לזיהוי בעיות ולטיפול בהן. ככל שבעיה מסוימת מופיעה בשלב מאוחר יותר במחזור החיים של הפיתוח, כך קשה ויקר יותר לטפל בה. הדבר נכון גם לגבי בעיות תקינות, אבל נכון גם לגבי בעיות בביצועים, כי הרבה מהבעיות האלה לא מטופלות באופן רטרואקטיבי לאחר המחויבות ל-codebase.
כיום, רוב המשובים על ביצועים מגיעים מחוץ למסגרת באמצעות תיעוד, ביקורות חד-פעמיות או שהם מוצגים מאוחר מדי באמצעות רגרסיה של מדדים אחרי הפריסה לייצור. אנחנו רוצים להביא זאת לזמן היצירה.
תאימות ב-frames
כדי לשמור על רף גבוה של חוויית משתמש בזמן הטעינה, אתם צריכים לענות על השאלות הבאות:
- מה ההגדרה של טעינה אופטימלית ומהן הבעיות הנפוצות שעלולות להשפיע לרעה?
- אילו פתרונות אפשר לשלב ולא צריכים קלט ממפתח?
- איך נוכל להבטיח שהמפתח ישתמש בפתרונות האלה וינצל אותם בצורה אופטימלית?
- אילו אפשרויות נוספות זמינות למפתח שמשפיעות על ביצועי הטעינה?
- מהם דפוסי הקוד שיכולים לתת לנו מידע על האפשרויות האלה (#3 ומס' 4 למעלה) בשלב מוקדם של תהליך היצירה?
- אילו כללים אפשר לנסח כדי להעריך את דפוסי הקוד האלה? איך אפשר להציג אותם למפתחים בזמן יצירת התוכן, תוך שילוב חלק בתהליך העבודה?
כדי לשלב את מודל התאימות שיש לנו ב-Google באופן פנימי ב-frameworks בקוד פתוח, הצוות שלנו ערך ניסויים רבים ב-Next.js, ואנחנו שמחים לשתף את החזון והתוכניות שלנו. הבנו שקבוצת הכללים הטובה ביותר שיכולה להעריך דפוסי קוד צריכה להיות שילוב של ניתוח קוד סטטי ובדיקות דינמיות. הכללים האלה יכולים להתפרס על כמה פלטפורמות, כולל:
- ESLint
- TypeScript
- בדיקות דינמיות בשרת הפיתוח של המשתמש (לאחר יצירת DOM)
- מודולים (Webpack)
- שימוש בכלים של CSS (עדיין בתהליך בדיקה)
השימוש בכללים באמצעות כלים שונים יאפשר לנו לוודא שהם עקביים, אבל גם כוללים בעיות בחוויית המשתמש שמשפיעות באופן ישיר על ביצועי הטעינה. בנוסף, אפשר להציג את הכללים האלה למפתחים גם בזמנים שונים:
- במהלך הפיתוח המקומי בשרת הפיתוח, בסביבת הפיתוח המשולבת (IDE) של הדפדפן ושל המשתמש יוצגו אזהרות, ויבקשו למפתחים לבצע שינויים קטנים בקוד.
- עם סיום תהליך ה-build, בעיות שלא נפתרו יוצגו שוב במסוף של המשתמש
בקצרה, צוותים יבחרו בתוצאות שחשובות להם, כמו מדדי ליבה לבדיקת חוויית המשתמש באתר או ביצועי הטעינה, ויפעילו מערכי כללים רלוונטיים לכל תורמי הקוד.
השיטה הזו עובדת ממש טוב בפרויקטים חדשים, אבל לא קל לשדרג מסדי קוד גדולים כדי לעמוד בכללים מלאים. ב-Google יש לנו מערכת נרחבת לביטול הסכמה ברמות שונות, כמו שורות בודדות של קוד מקור, ספריות שלמות, בסיסי קוד מדור קודם או חלקים של האפליקציה שלא נמצאים בפיתוח פעיל. אנחנו בוחנים באופן פעיל אסטרטגיות יעילות להבאת המידע הזה לצוותים באמצעות frameworks של קוד פתוח.
תאימות ב-Next.js
השימוש ב-ESLint נפוץ בקרב מפתחי JavaScript, ויותר מ-50% מהאפליקציות של Next.js משתמשות ב-ESLint בחלק מסוים מתהליך העבודה שלהם ב-build. ב-Next.js v11 הוספנו תמיכה ב-ESLint מוכנה מראש, שכוללת פלאגין מותאם אישית והגדרה שניתנת לשיתוף כדי לזהות בקלות בעיות נפוצות שספציפיות ל-framework במהלך הפיתוח ובזמן ה-build. כך מפתחים יכולים לפתור בעיות משמעותיות בזמן העריכה. לדוגמה, אם נעשה שימוש ברכיב מסוים או שלא נעשה בו שימוש, באופן שעלול לפגוע בביצועים, כמו באפשרות No HTML link for page (ללא קישור HTML לדף). לחלופין, אם גופן, גיליון סגנונות או סקריפט מסוימים עלולים להשפיע לרעה על טעינת משאבים בדף. לדוגמה, אין סקריפט סינכרוני.
בנוסף ל-ESLint, יש תמיכה בבדיקת סוגים משולבת גם בפיתוח וגם בייצור ב-Next.js מאז v9, עם תמיכה ב-TypeScript. מספר הרכיבים שה-framework סיפקה (תמונה, סקריפט, קישור) נבנו כהרחבה של רכיבי HTML (<img>
, <script>
, <a>
) כדי לספק למפתחים גישה ביצועית להוספת תוכן לדף אינטרנט. בדיקת הסוגים תומכת בשימוש הולם בתכונות האלה, בכך שהיא מבטיחה שהמאפיינים והאפשרויות שהוקצו יהיו בהיקף המקובל של הערכים והסוגים הנתמכים. ראו דוגמה בקטע רוחב וגובה של תמונה.
הצגת שגיאות באמצעות טוסטים ושכבות-על
כפי שצוין קודם, אפשר להציג כללי תאימות במספר תחומים. אנחנו בודקים כרגע את ההשקות ושכבות-העל כדי להציג שגיאות ישירות בדפדפן בסביבת הפיתוח המקומית של המשתמש.
הרבה כלים לבדיקת שגיאות ולביקורת שהמפתחים מסתמכים עליהם (Lighthouse, הכרטיסייה 'בעיות בכלי הפיתוח' ב-Chrome) הם פסיביים ונדרשת אינטראקציה כלשהי מצד המשתמש כדי לאחזר מידע. יש סיכוי גבוה יותר שהמפתחים יפעלו אם יתגלו שגיאות ישירות בכלים הקיימים שלהם, וכשהם מספקים פעולות קונקרטיות וספציפיות שצריך לבצע כדי לפתור את הבעיה.
תאימות במסגרות אחרות
אנחנו בודקים קודם את התאימות ב-Next.js כדי להרחיב את השימוש ב-frameworks אחרות (Nuxt, Angular וכו'). ב-ESLint וב-TypeScript כבר משתמשים ב-frameworks רבות בדרכים שונות, אבל הקונספט של מערכת זמן ריצה אחידה ברמת הדפדפן ממשיך לחקור.
סיכום
על פי תאימות, השיטות המומלצות מקובצות לקבוצות כללים שאפשר לפעול לפיהן למפתחים, בתור דפוסי קוד פשוטים. צוות Aurora התמקד בטעינת הביצועים, אבל שיטות מומלצות אחרות, כמו נגישות ואבטחה, הן רלוונטיות באותה מידה.
ציות לכללי התאימות אמור להוביל לתוצאות ניתנות לחיזוי, ועמידה ברף גבוה של חוויית המשתמש יכולה להיות תופעת לוואי של פיתוח סטאק התוכנות. תאימות מאפשרת לצוותים להיות פרודוקטיביים, ומבטיחה עמידה בר איכות גבוהה לאפליקציה, גם הצוותים ובסיסי הקוד גדלים לאורך הזמן.