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

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

ALT_TEXT_HERE

למה כדאי לפתח עוד לוח?

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

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

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

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

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

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

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

מספר טראקים באזור עריכה אחד

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

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

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

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

באמצעות שימוש ב-canvas אחד לכל ממשק המשתמש, היינו צריכים להבין איך לוודא שכל טראק מוצג בקואורדינטות הנכונות ולא גולש לטראק אחר. לדוגמה, אם טראק מסוים הוא בגובה של 100 פיקסלים, לא נוכל לאפשר לו לעבד סרטון בגובה של 120 פיקסלים ולשלול אותו לתוך המסלול שמתחתיו. כדי לפתור את הבעיה, אנחנו יכולים להשתמש ב-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 בהקשר של קנבס, ויכול להיות שהמקור שלו יהיה קנבס אחר.

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

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

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

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

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

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

בדיקת צילום מסך לממשק המשתמש של לוח הציור

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

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

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

סיכום

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

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

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

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

יצירת קשר עם צוות כלי הפיתוח ל-Chrome

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

  • שלחו לנו הצעה או משוב דרך crbug.com.
  • כדי לדווח על בעיה בכלי הפיתוח, לוחצים על אפשרויות נוספות   עוד   > עזרה > דיווח על בעיות בכלי הפיתוח בכלי הפיתוח.
  • אפשר לשלוח ציוץ אל @ChromeDevTools.
  • אפשר לכתוב תגובות לגבי 'מה חדש' בסרטוני YouTube בכלי הפיתוח או בסרטונים ב-YouTube בקטע 'טיפים לשימוש בכלי הפיתוח'.