איך ולמה יצרנו את התובנות לגבי הביצועים

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

ALT_TEXT_HERE

למה ליצור לוח נוסף?

(אם עדיין לא צפיתם בו, פרסמנו סרטון שמסביר למה יצרנו את החלונית 'תובנות לגבי ביצועים' ואיך אפשר להשתמש בה כדי לקבל תובנות פרקטיות לגבי ביצועי האתר).

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

נכנסים לחלונית התובנות, שבה עדיין אפשר לראות ציר זמן של המעקב ולבדוק את הנתונים, אבל גם לקבל רשימה שימושית של מה ש-DevTools מחשיב כ'תובנות' עיקריות ששווה להעמיק בהן. התובנות יזהו בעיות כמו בקשות לחסימת רינדור, שינויים בפריסה ומשימות ארוכות, ועוד כמה דוגמאות, שכולן יכולות להשפיע לרעה על ביצועי טעינת הדפים באתר, ובמיוחד על הציונים של Core Web Vital (CWV) באתר. בנוסף לסימון של בעיות, התובנות לגבי הביצועים יציגו הצעות פרקטיות לשיפור הדירוג של CWV שלכם, ויספקו קישורים למקורות מידע ולמסמכים נוספים.

הקישור למשוב בחלונית

החלונית הזו היא ניסיונית, ואנחנו רוצים לקבל ממך משוב. אם נתקלתם בבאגים או אם יש לכם בקשות להוספת תכונות שיעזרו לכם לשפר את ביצועי האתר, נשמח לשמוע מכם.

איך פיתחנו את התכונה 'תובנות לגבי הביצועים'

בדומה לשאר כלי הפיתוח, יצרנו את התובנות לגבי הביצועים ב-TypeScript והשתמשנו ברכיבי אינטרנט, שמגובים ב-lit-html, כדי לבנות את ממשק המשתמש. ההבדל בין 'תובנות לגבי ביצועים' לבין 'תובנות לגבי מודעות' הוא שממשק המשתמש הראשי הוא רכיב HTML‏ canvas, וציר הזמן מצויר על גבי הלוח הזה. רוב המורכבות נובעת מהניהול של הלוח: לא רק ציור הפרטים הנכונים במקום הנכון, אלא גם ניהול אירועי העכבר (לדוגמה: איפה המשתמש לחץ על הלוח? האם הם לחצו על אירוע שציירנו?) ולוודא שאנחנו מבצעים עיבוד מחדש של הלוח בצורה יעילה.

כמה טראקים בבד אחד

באתר נתון יש כמה 'טראקים' שאנחנו רוצים ליצור מהם רינדור, וכל אחד מהם מייצג קטגוריה אחרת של נתונים. לדוגמה, בחלונית התובנות יוצגו כברירת מחדל שלושה טראקים:

ככל שנוסיף תכונות לחלונית, נוסיף גם טראקים נוספים.

חשבנו בהתחלה שכל אחד מהטראקים האלה ייצור <canvas> משלו, כך שהתצוגה הראשית תהפוך למספר אלמנטים של קנבס בערימה אנכית. כך אפשר יהיה לפשט את העיבוד ברמת הטראק, כי כל טראק יכול לעבור עיבוד בנפרד ולא תהיה סכנה לעיבוד של טראק מחוץ לגבולות שלו. אבל לצערנו, לגישה הזו יש שתי בעיות עיקריות:

עיבוד (והצגה מחדש) של רכיבי canvas הוא יקר. שימוש בכמה קנבסים יקר יותר משימוש בקנבס אחד, גם אם הקנבס הזה גדול יותר. עיבוד שכבות-על שמופיעות בכמה טראקים (לדוגמה, קווים אנכיים לסימון אירועים כמו זמן FCP) הופך להיות מורכב: אנחנו צריכים לעבד את השכבות האלה בכמה משטחי קנבס ולוודא שכולן עוברות עיבוד יחד ומותאמות בצורה נכונה.

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

canvasContext.beginPath();
canvasContext.rect(
    trackVisibleWindow.x, trackVisibleWindow.y, trackVisibleWindow.width, trackVisibleWindow.height);
canvasContext.clip();

בנוסף, לא רצינו שכל טראק יצטרך לדעת מה המיקום שלו אנכית: כל טראק צריך להירנדר בעצמו כאילו הוא נרנדר ב-(0, 0), ויש לנו רכיב ברמה גבוהה יותר (שנקרא TrackManager) שמנהל את המיקום הכולל של הטראק. אפשר לעשות זאת באמצעות translate, שמעבירה את הלוח למיקום (x, y) נתון. לדוגמה:

canvasContext.translate(0, 10); // Translate by 10px in the y direction
canvasContext.rect(0, 0, 10, 10); // draw a rectangle at (0, 0) that’s 10px high and wide

למרות שהקוד rect מגדיר את 0, 0 כמיקום, התרגום הכולל שיוחל יגרום לעיבוד של המלבן ב-0, 10. כך אנחנו יכולים לעבוד על בסיס טראק כאילו אנחנו מבצעים רינדור ב-(0, 0), ולאפשר למנהל הטראקים לבצע תרגום בזמן שהוא מבצע רינדור של כל טראק, כדי לוודא שכל טראק ינוהל בצורה נכונה מתחת לטראק הקודם.

קנבסים מחוץ למסך לטראקים ולרגעים מיוחדים

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

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

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

כדי לפתור את הבעיה, חילקנו את ממשק המשתמש לשני משטחי ציור מחוץ למסך: משטח הציור 'הראשי', שבו מתבצע העיבוד של הטראקים, ומשטח הציור 'הרגעים המיוחדים', שבו מצוירים הרגעים המיוחדים. לאחר מכן אנחנו מעתיקים את הלוחות האלה ללוח אחד שגלוי למשתמש במסך. אפשר להשתמש בשיטה drawImage בהקשר של לוח, שיכול להשתמש בלוח אחר כמקור שלו.

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

ניתוח מעקב (trace) שנבדק באופן מקיף

אחד היתרונות של פיתוח תכונה חדשה מאפס הוא שאפשר לחשוב על הבחירות הטכניות שבוצעו בעבר ולבצע שיפורים. אחד מהדברים שרצינו לשפר היה לפצל את הקוד שלנו באופן מפורש לשני חלקים שונים כמעט לחלוטין:

מנתחים את קובץ המעקב ומוציאים את הנתונים הנדרשים. עיבוד של קבוצת טראקים.

הקפדה על הפרדה בין הניתוח (חלק 1) לבין עבודת ממשק המשתמש (חלק 2) אפשרה לנו ליצור מערכת ניתוח חזקה. כל מעקב עובר סדרה של רכיבי Handler שאחראים לבעיות שונות: LayoutShiftHandler מחשב את כל המידע שדרוש לתנודות הפריסה ו-NetworkRequestsHandler מטפל אך ורק בשליפת בקשות רשת. גם שלב הניתוח המפורש הזה, שבו יש לנו מנהלים שונים שאחראים על חלקים שונים של המעקב, היה שימושי: ניתוח המעקב יכול להיות מורכב מאוד, וקל יותר להתמקד בבעיה אחת בכל פעם.

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

בדיקת צילומי מסך של ממשק המשתמש של קנבס

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

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

בדיקות צילום המסך אינן מושלמות והן קהות במידה מועטה; ניתן רק לבדוק שהרכיב כולו מעובד כמצופה, ולא בטענות ספציפיות יותר, ובהתחלה נעשה שימוש יתר שנעשה בהן שימוש יתר כדי להבטיח שכל רכיב יחיד (HTML או בד ציור) מעובד כראוי. הדבר האט באופן משמעותי את חבילת הבדיקות שלנו, והוביל לבעיות שבהן שינויים קטנים ולא רלוונטיים כמעט בממשק המשתמש (כמו שינויים עדינים בצבע או הוספת שוליים בין פריטים) גרמו לכשל בכמה צילומי מסך והצריכו עדכון. הפכנו את השימוש שלנו בצילום מסך למצומצם יותר, והוא משמש אותנו רק לרכיבים שמבוססים על קנבס. האיזון הזה עבד לנו טוב עד עכשיו.

סיכום

בניית החלונית החדשה 'תובנות לגבי הביצועים' הייתה חוויה מהנה ומלמדת לצוות. למדנו המון על קובצי מעקב, עבודה עם קנבס ועוד. אנחנו מקווים שתיהנו להשתמש בחלונית החדשה. נשמח לקבל מכם משוב.

למידע נוסף על החלונית 'תובנות לגבי ביצועים', אפשר לעיין במאמר תובנות לגבי ביצועים: קבלת תובנות פרקטיות לגבי ביצועי האתר.

הורדת הערוצים לתצוגה מקדימה

מומלץ להשתמש ב-Chrome Canary, ב-Dev או ב-Beta כדפדפן הפיתוח שמוגדר כברירת מחדל. הערוצים לתצוגה מקדימה אלה מעניקים לך גישה לתכונות החדשות של כלי הפיתוח, מאפשרים לך לבדוק ממשקי API מתקדמים של פלטפורמות אינטרנט ולעזור לך לגלות בעיות באתר שלך לפני שהמשתמשים עושים זאת.

פנייה לצוות של כלי הפיתוח ל-Chrome

אתם יכולים להשתמש באפשרויות הבאות כדי לדון בתכונות החדשות, בעדכונים או בכל דבר אחר שקשור ל-DevTools.