בניית מודל האובייקטים

Ilya Grigorik
Ilya Grigorik

תאריך פרסום: 31 במרץ 2014

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

  • בייטים ← תווים ← אסימונים ← צמתים ← מודל אובייקט.
  • הרכיבים של ה-HTML עוברים טרנספורמציה ל-Document Object Model ‏(DOM), והרכיבים של ה-CSS עוברים טרנספורמציה ל-CSS Object Model ‏(CSSOM).
  • DOM ו-CSSOM הם מבני נתונים עצמאיים.
  • חלונית הביצועים של כלי הפיתוח של Chrome מאפשרת לנו לתעד ולבדוק את עלויות היצירה והעיבוד של DOM ו-CSSOM.

מודל אובייקטי מסמך (DOM)

<!DOCTYPE html>
<html>
  <head>
    <meta name="viewport" content="width=device-width,initial-scale=1" />
    <link href="style.css" rel="stylesheet" />
    <title>Critical Path</title>
  </head>
  <body>
    <p>Hello <span>web performance</span> students!</p>
    <div><img src="awesome-photo.jpg" /></div>
  </body>
</html>

רוצים לנסות?

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

תהליך היצירה של DOM

  1. המרה: הדפדפן קורא את הבייטים הגולמיים של ה-HTML מהדיסק או מהרשת ומתרגם אותם לתווים נפרדים על סמך הקידוד שצוין של הקובץ (לדוגמה, UTF-8).
  2. יצירת אסימונים: הדפדפן ממיר מחרוזות של תווים לאסימונים נפרדים, כפי שמפורט בתקן W3C HTML5, למשל <html>,‏ <body>, ומחרוזות אחרות בתוך סוגריים משולשים. לכל אסימון יש משמעות מיוחדת וסדרת כללים משלו.
  3. ניתוח תחבירי: האסימונים שנפלטים מומרים ל'אובייקטים' שמגדירים את המאפיינים והכללים שלהם.
  4. יצירת DOM: לבסוף, מאחר שסימון ה-HTML מגדיר קשרים בין תגים שונים (חלק מהתגים נכללים בתגים אחרים), האובייקטים שנוצרים מקושרים במבנה נתונים של עץ, שמתעד גם את יחסי ההורה-צאצא שהוגדרו בסימון המקורי: האובייקט HTML הוא הורה של האובייקט body, האובייקט body הוא הורה של האובייקט paragraph, וכן הלאה, עד שנוצרת ההצגה המלאה של המסמך.

עץ DOM

הפלט הסופי של התהליך כולו הוא מודל אובייקט המסמך (DOM) של הדף הפשוט שלנו, שבו הדפדפן משתמש לכל העיבוד הנוסף של הדף.

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

מעקב אחר יצירת DOM ב-DevTools

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

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

מודל אובייקטים של CSS (CSSOM)

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

body {
  font-size: 16px;
}

p {
  font-weight: bold;
}

span {
  color: red;
}

p span {
  display: none;
}

img {
  float: right;
}

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

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

שלבי בניית CSSOM

הבייטים של ה-CSS מומרים לתוים, לאחר מכן לאסימונים, לאחר מכן לצמתים, ולבסוף הם מקושרים למבנה עץ שנקרא 'מודל אובייקטים של CSS' (CSSOM):

עץ CSSOM

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

כדי להמחיש את הדוגמה הזו, קחו לדוגמה את עץ ה-CSSOM שתואר קודם. לכל טקסט שמופיע בתג <span> שממוקם ברכיב body יש גופן בגודל 16 פיקסלים והוא מודגש באדום – ההוראה font-size מועברת בירושה מה-body ל-span. עם זאת, אם span הוא צאצא של תג של פסקה (p), התוכן שלו לא מוצג.

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

כדי לבדוק כמה זמן נמשך עיבוד ה-CSS, אפשר לתעד את ציר הזמן בכלי הפיתוח ולחפש אירוע "Recalculate Style": בניגוד לניתוח DOM, ציר הזמן לא מציג ערך נפרד של "Parse CSS", אלא מתעד את ניתוח והבנייה של עץ CSSOM, וגם את החישוב הרקורסיבי של הסגנונות המחושבים באירוע היחיד הזה.

מעקב אחר היצירה של CSSOM בכלי הפיתוח

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

משוב