תאימות בסביבה העסקית של JavaScript framework
בפוסט המבוא בבלוג שלנו, תיארנו איך למדנו הרבה במהלך היצירה של מסגרות וכלים, והשימוש בהם לפיתוח ולתחזוקה של אפליקציות אינטרנט בקנה מידה גדול כמו חיפוש Google, מפות Google, Google Photos וכו'. על ידי הגנה על המפתחים מפני כתיבת קוד שעלול להשפיע לרעה על חוויית המשתמש, הוכיחנו שמסגרות יכולות לשחק תפקיד מפתח בשיפור הביצועים ואיכות האפליקציות.
ב-Google, השתמשנו במונח תאימות כדי לתאר את השיטה הזו, ובמאמר הזה נסביר איך אנחנו מתכננים להפוך את הקונספט הזה לקוד פתוח בסביבת ה-JavaScript framework.
מהי תאימות?
ב-Google, תהליך התאימות היה תהליך התפתחותי. הצוותים הסתמכו על קבוצה קטנה של מפתחים מנוסים מאוד, שביצעו בדיקות קוד מקיפות וסימנו דברים שהשפיעו על איכות האפליקציה ועל יכולת התחזוקה שלה, מעבר לבעיות תקינות. כדי להתאים את התהליך לצוותים הולכים וגדלים של מפתחי אפליקציות, פיתחנו מערכת תאימות שמאפשרת לקודד שיטות מומלצות באופן אוטומטי ואכיפות. כך אפשר להבטיח רמה גבוהה ועקבית של איכות האפליקציה ותחזוקת קוד הבסיס, ללא קשר למספר האנשים שתורמים לקוד.
תאימות היא מערכת שמאפשרת למפתחים להישאר בדרך הנכונה, מחזקת את הביטחון ומבטיחה תוצאות צפויות. היא מאפשרת לצוותים להיות פרודוקטיביים, והיא חיונית להרחבת היקף הפעילות – ככל שהצוותים גדלים ומפתחים יותר תכונות בו-זמנית. היא מאפשרת למפתחים להתמקד בפיתוח תכונות המוצר, ומפנה אותם מהפרטים הקטנים ומהמצב המשתנה בתחומים שונים כמו ביצועים, נגישות, אבטחה וכו'. כל אחד יכול לבטל את ההסכמה ל-Conformance בכל שלב, והוא צריך להיות מותאם אישית כך שלצוותים תהיה אפשרות לאכוף את מה שהם מחויבים אליו.
התאימות מבוססת על ברירת מחדל חזקה ועל מתן כללים שניתן לבצע בהם פעולה שאפשר לאכוף בזמן הכתיבה. העקרונות האלה מתחלקים ל-3 קטגוריות:
1. ברירות מחדל חזקות
אחד מהיבטים הבסיסיים של תאימות הוא לוודא שלכלים שבהם המפתחים משתמשים יש הגדרות ברירת מחדל חזקות. פירוש הדבר הוא שהפתרונות לא רק מוטמעים במסגרות, אלא גם דפוסי העיצוב של המסגרות מאפשרים לבצע את הפעולות הנכונות בקלות ומונע מהמפתחים לפעול לפי דפוסים שגויים. המסגרת תומכת במפתחים בתכנון האפליקציה ובמבנה הקוד.
כדי לשפר את ביצועי הטעינה, צריך לבצע אופטימיזציה של כל משאב (גופנים, CSS, JavaScript, תמונות וכו'). זוהי בעיה מורכבת שכוללת חיתוך ביטים, צמצום של נסיעות הלוך ושוב והפרדה בין מה שנחוץ לעיבוד הגרפי הראשון, לנכונות החזותית ולאינטראקציה עם המשתמש. לדוגמה, חילוץ CSS קריטי והגדרת תעדוף לתמונות חשובות.
2. כללים לפעולה
גם אחרי שמבצעים אופטימיזציות בסיסיות, המפתחים עדיין צריכים לקבל החלטות. יש מגוון אפשרויות לאופטימיזציה, בהתאם לכמות המידע שדרוש מהמפתחים:
- הגדרות ברירת מחדל שלא דורשות קלט מהמפתחים, כמו הטמעת CSS קריטי.
- דרישה להבעת הסכמה מצד המפתחים. לדוגמה, שימוש ברכיב תמונה שסופק על ידי המסגרת כדי לשנות את הגודל והמידה של תמונות.
- מחייב התאמה אישית והבעת הסכמה מצד המפתח. לדוגמה, תוכלו לתייג תמונות חשובות כדי שהן ייטענו מוקדם.
- לא תכונה ספציפית, אלא דברים שעדיין דורשים החלטה של המפתחים. לדוגמה, הימנעות מגופנים או מסקריפטים סינכרוניים שמתעכבים ברינדור מוקדם.
אופטימיזציות שדורשות החלטה מצד המפתחים עלולות לסכן את הביצועים של האפליקציה. ככל שמוסיפים תכונות והצוות מתרחב, גם המפתחים הכי מנוסים לא יכולים לעמוד בקצב השינויים בשיטות המומלצות, וגם זה לא השימוש הטוב ביותר בזמן שלהם. כדי לוודא שהאפליקציה תמשיך לעמוד בתקן מסוים גם כשהמפתחים ימשיכו לבצע שינויים, כללים מתאימים שאפשר לבצע בהם פעולה חשובים כמו הגדרות ברירת מחדל חזקות.
3. מועד הכתיבה
חשוב לזהות בעיות בביצועים ולמנוע אותן בשלב מוקדם במחזור החיים של הפיתוח. זמן הכתיבה, לפני שמחויבים את הקוד, הוא הזמן המתאים ביותר לזהות בעיות ולטפל בהן. ככל שמזהים בעיה מאוחר יותר במחזור החיים של הפיתוח, כך קשה יותר ויותר לטפל בה, והעלות של הטיפול בה גדלה. הכלל הזה רלוונטי לבעיות תקינות, אבל גם לבעיות בביצועים, כי הרבה מהבעיות האלה לא יטופלו באופן רטרואקטיבי אחרי שהן ייכללו בקוד.
כיום, רוב המשוב על הביצועים מגיע מחוץ לתהליך, באמצעות מסמכים, ביקורות חד-פעמיות או מאוחר מדי באמצעות רגרסיה של מדדים אחרי הפריסה בסביבת הייצור. אנחנו רוצים להביא את התכונה הזו לשלב הכתיבה.
תאימות במסגרות
כדי לשמור על רמה גבוהה של חוויית משתמש בביצועי הטעינה, צריך לענות על השאלות הבאות:
- מהי טעינה אופטימלית, ואילו בעיות נפוצות עלולות להשפיע עליה לרעה?
- אילו פתרונות אפשר להטמיע מראש בלי צורך בתכנות מצד המפתחים?
- איך אנחנו יכולים לוודא שהמפתחים משתמשים בפתרונות האלה ומפיקים מהם את המקסימום?
- אילו אפשרויות אחרות יכול המפתח לבחור שמשפיעות על ביצועי הטעינה?
- מהם דפוסי הקוד שיכולים לספר לנו על הבחירות האלה (3 ו-4 למעלה) בשלב מוקדם של כתיבת הקוד?
- אילו כללים אפשר לנסח כדי להעריך את דפוסי הקוד האלה? איך אפשר להציג אותם למפתח בזמן הכתיבה, תוך שילוב חלק בתהליך העבודה שלו?
כדי להעביר את מודל התאימות שאנחנו משתמשים בו ב-Google למסגרות קוד בקוד פתוח, הצוות שלנו ערך ניסויים רבים ב-Next.js, ואנחנו שמחים לשתף את התובנות והתוכניות שלנו. הבנו שקבוצת הכללים הטובה ביותר שיכולה להעריך דפוסי קוד צריכה להיות שילוב של ניתוח קוד סטטי ובדיקות דינמיות. הכללים האלה יכולים לחול על כמה פלטפורמות, כולל:
- ESLint
- TypeScript
- בדיקות דינמיות בשרת הפיתוח של המשתמש (לאחר יצירת DOM)
- ארגון מודולים בחבילה (webpack)
- כלי CSS (עדיין בבדיקה)
היתרון של הוספת כללים באמצעות כלים שונים הוא שאנחנו יכולים לוודא שהם עקביים, אבל גם לכלול בעיות בחוויית המשתמש שמשפיעות ישירות על ביצועי הטעינה. בנוסף, אפשר להציג את הכללים האלה למפתחים גם בזמנים שונים:
- במהלך הפיתוח המקומי בשרת הפיתוח, יוצגו אזהרות בדפדפן ובסביבת הפיתוח המשולבת (IDE) של המשתמש, שתעודדו את המפתחים לבצע שינויים קטנים בקוד.
- בזמן ה-build, בעיות שלא נפתרו יופיעו שוב במסוף של המשתמש.
בקצרה, הצוותים יבחרו את התוצאות שהם רוצים להשיג, כמו מדדי Core Web Vitals או ביצועי טעינה, ויפעילו כללי קוד רלוונטיים שכל שותפי הקוד יצטרכו לפעול לפיהם.
השיטה הזו עובדת מצוין בפרויקטים חדשים, אבל לא קל לשדרג בסיס קוד גדול כך שיתאים לכל כללי המדיניות. ב-Google יש לנו מערכת מקיפה לביטול ההסכמה ברמות שונות, כמו שורות בודדות של קוד מקור, ספריות שלמות, גרסאות קודקוד קודמות או חלקים באפליקציה שלא נמצאים בפיתוח פעיל. אנחנו בודקים אסטרטגיות יעילות להעברת היכולות האלה לצוותים באמצעות מסגרות קוד פתוח.
תאימות ב-Next.js
ESLint נמצא בשימוש נרחב בקרב מפתחי JavaScript, ויותר מ-50% מהאפליקציות של Next.js משתמשות ב-ESLint בחלק כלשהו מתהליך ה-build. בגרסה 11 של Next.js נוספה תמיכה מובנית ב-ESLint, שכוללת יישום פלאגין בהתאמה אישית והגדרות שאפשר לשתף, כדי שיהיה קל יותר לזהות בעיות נפוצות שספציפיות למסגרת במהלך הפיתוח ובזמן ה-build. כך המפתחים יכולים לתקן בעיות משמעותיות כבר בשלב הכתיבה. לדוגמה, כשמשתמשים ברכיב מסוים או לא משתמשים בו בצורה שעלולה לפגוע בביצועים (כמו אין קישור HTML לדף). לחלופין, אם גופן, סגנון גיליון או סקריפט מסוימים יכולים להשפיע לרעה על טעינת המשאבים בדף. לדוגמה, No synchronous script.
בנוסף ל-ESLint, יש תמיכה ב-Next.js בבדיקת סוגים משולבת גם בפיתוח וגם בסביבת הייצור, החל מגרסה 9 עם תמיכה ב-TypeScript. כמה רכיבים שסופקו על ידי המסגרת (תמונה, סקריפט, קישור) נוצרו כהרחבה של רכיבי HTML (<img>
, <script>
, <a>
) כדי לספק למפתחים גישה יעילה להוספת תוכן לדף אינטרנט. בדיקת הטיפוס תומכת בשימוש הולם בתכונות האלה על ידי הבטחה שהמאפיינים והאפשרויות שהוקצו נמצאים בהיקף הקביל של הערכים והסוגי הנתמכים. לדוגמה, תוכלו לעיין בקטע רוחב וגובה נדרשים של תמונה.
הצגת שגיאות באמצעות הודעות טוסט ושכבות-על
כפי שצוין קודם, אפשר להציג כללי תאימות בכמה אזורים. אנחנו בודקים כרגע את האפשרות להציג הודעות טוסט ושכבות-על כדרך להציג שגיאות ישירות בדפדפן בסביבת הפיתוח המקומית של המשתמש.
הרבה כלים לבדיקת שגיאות וביקורת שמפתחים מסתמכים עליהם (Lighthouse, הכרטיסייה 'בעיות' בכלי הפיתוח ל-Chrome) הם פסיביים, ודורשים צורת אינטראקציה כלשהי עם המשתמש כדי לאחזר מידע. סביר יותר שמפתחים יפעלו כשהשגיאות יוצגו ישירות בכלים הקיימים שלהם, וכשהם יקבלו הוראות מפורטות וספציפיות לפעולות שצריך לבצע כדי לפתור את הבעיה.
תאימות במסגרות אחרות
אנחנו בודקים את התאימות ב-Next.js קודם, במטרה להרחיב אותה למסגרות אחרות (Nuxt, Angular וכו'). כבר נעשה שימוש ב-ESLint וב-TypeScript במסגרות רבות ובדרכים רבות ושונות, אבל אנחנו בודקים באופן פעיל את הרעיון של מערכת רציפה ועקבית בסביבת זמן ריצה ברמת הדפדפן.
סיכום
תוכן התאימות כולל שיטות מומלצות שמקודדות בכללי קוד שמפתחים יכולים להשתמש בהם כדוגמאות קוד פשוטות. צוות Aurora התמקד בביצועי הטעינה, אבל שיטות מומלצות אחרות, כמו נגישות ואבטחה, רלוונטיות באותה מידה.
ציות לכללי התאימות אמור להוביל לתוצאות צפויות, והשגת רף גבוה של חוויית משתמש יכולה להיות תופעת לוואי של פיתוח על גבי סטאק הטכנולוגיה שלכם. תאימות מאפשרת לצוותים להיות פרודוקטיביים ומבטיחה רף איכות גבוה לאפליקציה, גם כשהצוותים ופלטפורמות הקוד גדלים עם הזמן.