قبل از اینکه مرورگر بتواند صفحه را رندر کند، باید درخت های DOM و CSSOM را بسازد. در نتیجه، باید اطمینان حاصل کنیم که هر دو HTML و CSS را در سریع ترین زمان ممکن به مرورگر تحویل می دهیم.
خلاصه
- بایت ها → کاراکترها → نشانه ها → گره ها → مدل شی.
- نشانه گذاری HTML به یک مدل شی سند (DOM) تبدیل می شود. نشانه گذاری CSS به یک مدل شیء CSS (CSSOM) تبدیل می شود.
- DOM و CSSOM ساختارهای داده مستقلی هستند.
- پانل عملکرد Chrome DevTools به ما امکان می دهد هزینه های ساخت و پردازش 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 ساده با مقداری متن و یک تصویر واحد. مرورگر چگونه این صفحه را پردازش می کند؟
- تبدیل: مرورگر بایتهای خام HTML را از روی دیسک یا شبکه میخواند و آنها را بر اساس رمزگذاری مشخص شده فایل (به عنوان مثال UTF-8) به کاراکترهای جداگانه ترجمه میکند.
- Tokenizing: مرورگر رشتههایی از کاراکترها را به نشانههای متمایز تبدیل میکند - همانطور که توسط استاندارد W3C HTML5 برای مثال، "<html>"، "<body>" - و رشتههای دیگر در براکتهای زاویه مشخص شده است. هر توکن معنای خاصی دارد و مجموعه قوانین خاص خود را دارد.
- Lexing: نشانه های منتشر شده به "اشیاء" تبدیل می شوند که ویژگی ها و قوانین آنها را تعریف می کنند.
- ساخت DOM: در نهایت، چون نشانه گذاری HTML روابط بین تگ های مختلف را تعریف می کند (برخی از برچسب ها در تگ های دیگر قرار دارند)، اشیاء ایجاد شده در یک ساختار داده درختی پیوند داده می شوند که همچنین روابط والد-فرزند تعریف شده در نشانه گذاری اصلی را نشان می دهد: شی HTML والد جسم بدن است، بدن والد شی پاراگراف است و غیره.
خروجی نهایی کل این فرآیند، Document Object Model (DOM) صفحه ساده ما است که مرورگر برای تمام پردازش های بعدی صفحه از آن استفاده می کند.
هر بار که مرورگر نشانهگذاری HTML را پردازش میکند، تمام مراحل بالا را طی میکند: تبدیل بایت به کاراکتر، شناسایی نشانهها، تبدیل نشانهها به گرهها و ساخت درخت DOM. کل این فرآیند ممکن است کمی طول بکشد، به خصوص اگر مقدار زیادی HTML برای پردازش داشته باشیم.
اگر Chrome DevTools را باز کنید و زمانی که صفحه بارگذاری میشود خط زمانی را ضبط کنید، میتوانید زمان واقعی انجام این مرحله را مشاهده کنید—در مثال بالا، تبدیل یک تکه از HTML به درخت DOM حدود 5 میلیثانیه طول کشید. برای یک صفحه بزرگتر، این فرآیند می تواند به طور قابل توجهی بیشتر طول بکشد. هنگام ایجاد انیمیشن های روان، اگر مرورگر مجبور باشد مقادیر زیادی HTML را پردازش کند، به راحتی می تواند به یک گلوگاه تبدیل شود.
درخت DOM ویژگیها و روابط نشانهگذاری سند را نشان میدهد، اما به ما نمیگوید که عنصر در هنگام رندر چگونه به نظر میرسد. این مسئولیت CSSOM است.
مدل شیء CSS (CSSOM)
هنگامی که مرورگر در حال ساخت DOM صفحه ساده ما بود، با یک برچسب پیوند در بخش سر سند که به یک شیوه نامه خارجی CSS ارجاع می دهد، برخورد کرد: style.css
. با پیش بینی اینکه برای ارائه صفحه به این منبع نیاز دارد، بلافاصله درخواستی برای این منبع ارسال می کند که با محتوای زیر برمی گردد:
body {
font-size: 16px;
}
p {
font-weight: bold;
}
span {
color: red;
}
p span {
display: none;
}
img {
float: right;
}
ما میتوانستیم سبکهای خود را مستقیماً در نشانهگذاری HTML (داخلی) اعلام کنیم، اما مستقل نگه داشتن CSS خود از HTML به ما امکان میدهد تا محتوا و طراحی را به عنوان دغدغههای جداگانه در نظر بگیریم: طراحان میتوانند روی CSS کار کنند، توسعهدهندگان میتوانند روی HTML تمرکز کنند و غیره.
همانند HTML، باید قوانین CSS دریافتی را به چیزی تبدیل کنیم که مرورگر بتواند آن را بفهمد و با آن کار کند. بنابراین، ما فرآیند HTML را تکرار می کنیم، اما برای CSS به جای HTML:
بایتهای CSS به کاراکترها، سپس توکنها، سپس گرهها تبدیل میشوند و در نهایت به یک ساختار درختی معروف به "CSS Object Model" (CSSOM) پیوند داده میشوند.
چرا CSSOM ساختار درختی دارد؟ هنگام محاسبه مجموعه نهایی سبکها برای هر شی در صفحه، مرورگر با کلیترین قانون قابل اجرا برای آن گره شروع میکند (به عنوان مثال، اگر فرزند یک عنصر بدنه است، پس همه سبکهای بدن اعمال میشوند) و سپس به صورت بازگشتی اصلاح میکند. سبک های محاسبه شده با اعمال قوانین خاص تر. یعنی قوانین «آبشار پایین میآیند».
برای ملموس تر کردن آن، درخت CSSOM را در بالا در نظر بگیرید. هر متن موجود در تگ <span>
که در عنصر بدنه قرار میگیرد، دارای اندازه قلم 16 پیکسل و دارای متن قرمز است—دستورالعمل font-size
از body
به span
آبشاری میکند. با این حال، اگر یک تگ span
فرزند تگ پاراگراف ( p
) باشد، محتوای آن نمایش داده نمی شود.
همچنین، توجه داشته باشید که درخت فوق، درخت کامل CSSOM نیست و فقط سبکهایی را نشان میدهد که ما تصمیم گرفتیم آنها را در stylesheet خود لغو کنیم. هر مرورگر یک مجموعه پیشفرض از سبکها را ارائه میکند که به نام «سبکهای عامل کاربر» نیز شناخته میشوند - این همان چیزی است که وقتی هیچ یک از سبکهای خود را ارائه نمیکنیم، میبینیم - و سبکهای ما به سادگی این پیشفرضها را لغو میکنند.
برای اینکه بفهمید پردازش CSS چقدر طول می کشد، می توانید یک جدول زمانی را در DevTools ضبط کنید و به دنبال رویداد "Recalculate Style" بگردید: برخلاف تجزیه DOM، خط زمانی یک ورودی جداگانه "Parse CSS" را نشان نمی دهد و در عوض تجزیه و درخت CSSOM را ضبط می کند. ساخت و ساز، به علاوه محاسبه بازگشتی سبک های محاسبه شده تحت این یک رویداد.
شیوه نامه بی اهمیت ما حدود 0.6 میلی ثانیه طول می کشد تا پردازش شود و هشت عنصر را در صفحه تحت تأثیر قرار دهد — نه زیاد، اما یک بار دیگر رایگان نیست. با این حال، هشت عنصر از کجا آمده اند؟ CSSOM و DOM ساختارهای داده مستقلی هستند! به نظر می رسد، مرورگر یک مرحله مهم را پنهان می کند. در مرحله بعد، اجازه دهید در مورد درخت رندر که DOM و CSSOM را به هم پیوند می دهد صحبت کنیم.