איך גדלים של DOM גדולים משפיעים על האינטראקטיביות ומה אפשר לעשות בקשר אליה

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

אין דרך לעקוף את זה: כשיוצרים דף אינטרנט, לדף הזה יהיה Document Object Model (DOM). ה-DOM מייצג את מבנה ה-HTML של הדף, ומעניק ל-JavaScript ול-CSS גישה למבנה ולתוכן של הדף.

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

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

מתי ה-DOM של דף גדול מדי?

לפי Lighthouse, גודל ה-DOM של דף חורג מהמגבלה של 1,400 צמתים. מערכת Lighthouse תתחיל להציג אזהרות כשה-DOM של דף יחרוג מ-800 צמתים. ניקח לדוגמה את קוד ה-HTML הבא:

<ul>
  <li>List item one.</li>
  <li>List item two.</li>
  <li>List item three.</li>
</ul>

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

איך DOMs גדולים משפיעים על ביצועי הדפים?

רכיבי DOM גדולים משפיעים על ביצועי הדף בכמה דרכים:

  1. במהלך העיבוד הראשוני של הדף. כשמחילים CSS על דף, נוצר מבנה דומה ל-DOM שנקרא מודל אובייקטים של CSS (CSSOM). ככל שהספציפיות של הסלקטורים ב-CSS משתפרים, ה-CSSOM הופך למורכב יותר ונדרש זמן רב יותר כדי להפעיל את הפריסה, העיצוב, החיבור והצביעה שנדרשים למשיכת דף האינטרנט למסך. העבודה הנוספת הזו מאריכה את זמן האחזור של אינטראקציות שמתרחשות בשלב מוקדם במהלך טעינת הדף.
  2. כאשר אינטראקציות משנות את ה-DOM, באמצעות הוספה או מחיקה של רכיבים או על ידי שינוי תוכן וסגנונות של DOM, העבודה הנחוצה לעיבוד עדכון זה עלולה להוביל לעלויות יקרות מאוד של פריסה, עיצוב, איחוד וצביעה. בדומה לעיבוד הראשוני של הדף, שיפור הספציפיות של סלקטור ב-CSS עשויה להגדיל את עיבוד הנתונים כאשר רכיבי HTML מוכנסים ל-DOM כתוצאה מאינטראקציה.
  3. כש-JavaScript שולח שאילתה ל-DOM, הפניות לרכיבי DOM מאוחסנות בזיכרון. לדוגמה, אם קוראים ל-document.querySelectorAll כדי לבחור את כל רכיבי <div> בדף, עלות הזיכרון עשויה להיות משמעותית אם התוצאה מחזירה מספר גדול של רכיבי DOM.
צילום מסך של משימה ארוכה שנגרמה עקב רינדור יתר בחלונית הביצועים בחלונית הביצועים של כלי הפיתוח ל-Chrome. מחסנית הקריאות של המשימה הארוכה מראה זמן משמעותי שהוקדש לחישוב מחדש של סגנונות דפים, וגם לצביעה מראש.
משימה ארוכה, שמוצגת בכלי לניתוח הביצועים (Performance profiler) ב-Chrome DevTools. המשימה הארוכה שמוצגת נובעת מהוספת רכיבי DOM ל-DOM גדול באמצעות JavaScript.

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

איך מודדים גודל DOM?

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

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

document.querySelectorAll('*').length;

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

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

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

איך אפשר למדוד את מספר רכיבי ה-DOM שהושפעו מאינטראקציה?

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

צילום מסך של פעילות החישוב מחדש של הסגנון שנבחר בחלונית הביצועים בכלי הפיתוח ל-Chrome. בחלק העליון של מסלול האינטראקציות מוצגת אינטראקציה של קליק, ורוב העבודה מושקעת בחישוב מחדש של סגנון ובעיבוד לפני הצביעה. בתחתית המסך מוצגת חלונית עם פרטים נוספים על הפעילות שנבחרה, ומדווחת ש-2,547 רכיבי DOM הושפעו ממנה.
עיון במספר הרכיבים שהושפעו ב-DOM כתוצאה מעבודת חישוב מחדש של הסגנון. חשוב לשים לב שהחלק המוצלל של האינטראקציה במסלול האינטראקציות מייצג את החלק של משך האינטראקציה שנמשך יותר מ-200 אלפיות השנייה, שהוא הסף 'הטוב' שמוגדר ל-INP.

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

איך אפשר להקטין את גודל ה-DOM?

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

<div>
  <div>
    <div>
      <div>
        <!-- Contents -->
      </div>
    </div>
  </div>
</div>

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

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

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

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

אסטרטגיות אחרות שכדאי לשקול

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

כדאי לשקול גישה נוספת

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

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

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

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

הגבלת המורכבות של סלקטור ב-CSS

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

שימוש בנכס content-visibility

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

סיכום

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

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

תמונה ראשית (Hero) מ-UnFlood, מאת Louis Reed.