في هذه الصفحة
المقدمة
لو سألت نفسك إزاي المتصفح بيقدر يعرض صفحة ويب كاملة قدامك بعد ما تضغط على لينك؟ الموضوع دا بيعدي بكذا خطوة مهمة، وكل خطوة ليها شغل مختلف وبتأثر بشكل مباشر على سرعة تحميل الصفحة وتجربة المستخدم.
بناء شجرتين DOM و CSSOM
عشان المتصفح يقدر يعرض (يـ render) الصفحة، أول حاجة بيعملها إنه يبني شجرتين شجرة الـ DOM وشجرة الـ CSSOM.
- الـ "DOM "Document Object Model: دي شجرة بتمثل كل عنصر HTML في الصفحة.
- الـ "CSSOM "CSS Object Model: دي شجرة بتمثل الـ styles اللي بتحدد شكل الصفحة (الـ CSS).
المتصفح محتاج يبني الشجرتين دول عشان يعرف إزاي هيتعامل مع كل عنصر في الصفحة وأشكاله من الـ CSS.
ليه بناء الشجرتين دول مهم؟
الـ DOM بيحدد المحتوى اللي هيظهر، والـ CSSOM بيحدد شكله، وبالتالي المتصفح لازم يعرف التنسيق النهائي لكل عنصر في الصفحة قبل ما يرسمه (يـ render). بعد ما المتصفح يبني الشجرتين دول، بيبدأ يجمعهم في خطوة مهمة اسمها "شجرة العرض" (render tree)، ودي اللي بتربط المحتوى بالتصميم وتخلي المتصفح يقدر يرسم العناصر بالشكل المطلوب.
رحلة الـ HTML والـ CSS لحد ما تبقى صفحة مرئية من الـ Bytes للشاشة
- البيانات (Bytes) بتتحول لحروف (characters) → رموز (tokens) → عقد (nodes) → وفي الآخر بتتحول لـ object model.
- الـ HTML Markup بيتحول لـ Document Object Model" DOM"، والـ CSS Markup بيتحول لـ CSS Object Model" CSSOM".
- الـ DOM و CSSOM هما Data Structures مستقلين عن بعض.
- في Chrome DevTools، تقدر تستخدم Performance Panel عشان تـ Capture وتـ Inspect الـ Costs لبناء ومعالجة الـ DOM والـ CSSOM.
إزاي المتصفح بيحوّل الـ HTML الخام اللي جاي من الشبكة أو الهارد لحاجة يقدر يعرضها على الشاشة؟ العملية دي بتعدي في كذا مرحلة، كل مرحلة لها شغل معين، تعالوا نفهمهم مع بعض.
الـ (DOM) Document Object Model
لو عندك Document Object Model" 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>
- الـ (Conversion): أول خطوة المتصفح بيعملها هي إنه يقرأ الـ HTML الخام اللي جاي سواء من النت أو من الديسك، ويبدأ يحول البايتس دي لحروف (characters) حسب الـ encoding اللي متحدد للملف، زي UTF-8 مثلًا.
- الـ (Tokenizing): بعد ما الحروف اتقرت، المتصفح بيحولهم لتوكنز (Tokens) مميزة زي <html>, <body> ودي أكواد المتصفح فاهم إنها بتمثل عناصر ليها قواعد معينة (W3C HTML5 standard)
- الـ (Lexing): بعد الـTokenizing، المتصفح بيحوّلهم لـ "objects" اللي بتعرف خواص كل عنصر والقواعد بتاعته، يعني إيه اللي ممكن أو مينفعش يتعمل مع العنصر ده.
- بناء الـ DOM "DOM Construction": في المرحلة دي، المتصفح بيربط الـ objects دي ببعضها في شجرة (tree) بتوضح الـ relationships ما بينهم، زي العلاقة بين الـ parent والـ child. مثلًا، عنصر <html> بيكون الـ parent للـ <body>، وده بيكون الـ parent للـ <p>، وهكذا.
النتيجة النهائية لكل العملية دي هي تكوين الـ Document Object Model (DOM) بتاع الصفحة البسيطة اللي عندنا، وده اللي المتصفح بيستخدمه في كل المعالجة اللي بتحصل بعد كده للصفحة.
تقدروا دلوقتي تشتركوا في النشرة الأسبوعية لاقرأ-تِك بشكل مجاني تمامًا عشان يجيلكوا كل جديد بشكل أسبوعي فيما يخص مواضيع متنوعة وبشروحات بسيطة وسهلة وبجودة عالية 🚀
النشرة هيكون ليها شكل جديد ومختلف عن شكلها القديم وهنحاول انها تكون مميزة ومختلفة وخليط بين المحتوى الأساسي اللي بينزل ومفاجآت تانية كتير 🎉
بفضل الله قمنا بإطلاق قناة اقرأ-تِك على التليجرام مجانًا للجميع 🚀
آملين بده اننا نفتح باب تاني لتحقيق رؤيتنا نحو إثراء المحتوى التقني باللغة العربية ، ومساعدة لكل متابعينا في انهم يوصلوا لجميع أخبار اقرأ-تِك من حيث المقالات ومحتوى ورقة وقلم والنشرة الأسبوعية وكل جديد بطريقة سريعة وسهلة
مستنينكوا تنورونا , وده رابط القناة 👇
كل مرة المتصفح بيشتغل على الـ HTML اللي جاي، بيمر بنفس الخطوات اللي اتكلمنا عنها: يحول البايتس لحروف، يتعرف على التوكنز، يحولهم لعناصر (nodes)، ويبدأ يبني شجرة الـ DOM. العملية دي ممكن تاخد وقت، خصوصًا لو كمية الـ HTML كبيرة أو معقدة علشان كده مهم نكون دايمًا بنفكر في تقليل حجم الـ HTML اللي بنبعت للمتصفح عشان نسرّع العملية دي!
ملاحظة: هنا بنفترض إنك عندك خلفية بسيطة عن Chrome DevTools – يعني تعرف إزاي تـ Capture الـ Network Waterfall أو تسجل Timeline
لو محتاج تفتكر بسرعة، ممكن تبص على Chrome DevTools Documentation؛ ولو أول مرة تستخدمها، شوف DevTools for Beginners في Documentation!
لو فتحت Chrome DevTools وسجلت Timeline أثناء تحميل الصفحة، هتقدر تشوف الوقت الفعلي اللي أخدته العملية دي – في المثال اللي فوق، خد حوالي 5 ملي ثانية عشان نحول جزء من الـ HTML لشجرة DOM. لو الصفحة كانت أكبر، العملية دي ممكن تاخد وقت أطول بكتير. في حالة الـ Smooth Animations، الموضوع ده ممكن يبقى Bottleneck لو المتصفح مضطر يـ Process كميات كبيرة من الـ HTML.
شجرة الـ DOM بتـ Captures الـ Properties and Relationships بتاعة الـ HTML اللي عندك بس مش بتوضح إزاي العناصر هتظهر على الشاشة بعد الـ Rendering. وهنا ييجي دور الـ CSSOM.
الـ CSS Object Model (CSSOM)
وإنت بتبني شجرة الـ DOM للصفحة البسيطة بتاعتك، المتصفح بيلاقي تاج في الـ بتاع الصفحة اللي بيشير لملف CSS خارجي style.css المتصفح بيكون متوقع إنه محتاج الريسورس ده عشان يعرف يعمل Render للصفحة، فبسرعة بيبعت طلب للملف ده، ولما الطلب يرجع، بيكون فيه محتوى زي ده.
body {
font-size: 16px;
}
p {
font-weight: bold;
}
span {
color: red;
}
p span {
display: none;
}
img {
float: right;
}
ممكن كنا نكتب الـ Styles بتاعتنا مباشرة جوا الـ (HTML Inline)، لكن لو فصلنا الـ CSS عن الـ HTML، ده بيسمح لنا نتعامل بمبدأ Separate Concerns تفصل المحتوي عن الـ CSS.
لكن برضه، زي ما عملنا مع الـ HTML، محتاجين نحول الـ CSS اللي استلمناه لشيء المتصفح يقدر يفهمه ويتعامل معاه. فبالتالي، بنكرر عملية الـ HTML، لكن للـ CSS المرة دي.
ليه الـ CSSOM ليه Tree Structure لما المتصفح بيحسب مجموعة الـ Styles لأي عنصر في الصفحة، بيبدأ بالـ General Rule للي تنطبق على العنصر ده (زي إنه لو كان ابن لعنصر <body>, فكل الـ Styles الخاصة بالـ <body> بتطبق عليه) وبعدين بيبدأ يعدل الـ Styles عن طريق تطبيق الـ Specific Rules يعني القواعد "Cascade Down" - "بتتساقط لأسفل" تقدر تقول Inheritance.
خلينا نوضح الكلام ده أكتر. تخيل الـ CSSOM شجرة بالشكل اللي فوق. أي نص موجود داخل الـ <span> اللي داخل عنصر الـ <body>, هيكون حجمه 16 بكسل ولونه أحمر directive الـ font-size بيـ cascades down من الـ <body> للـ <span> لكن لو كان الـ <span> ابن لعنصر <p>, ساعتها المحتوى بتاعه مش هيظهر.
وبرضه، خليك عارف إن الشجرة اللي فوق مش هي الشجرة الكاملة للـ CSSOM، دي بس بتظهر الـ styles اللي قررنا نـ override في ملف الـ styles بتاعنا كل متصفح بيقدم مجموعة styles افتراضية معروفة بـ "user agent styles"—ودي اللي بنشوفها لما مابنكونش موفرين أي styles خاصة بينا—الـ styles اللي بنحطها بتـ override الـ default styles.
ولما تحب تعرف الوقت اللي بياخده processing الـ CSS، ممكن تسجل timeline في DevTools وتدور على حدث "Recalculate Style": وعلى عكس parsing الـ DOM، الـtimeline مابيشيرش إلى إدخال منفصل لـ "Parse CSS"، وبدل كده بيجمع بين الـparsing وبناء شجرة الـ CSSOM، بالإضافة للـrecursive calculation للـ computed styles تحت نفس الـ event
في الختام
الـ stylesheet بتاعنا الغلبان اللي فوق دا أخد حوالي 0.6 مللي ثانية عشان يـ process وبيأثر على 8 عناصر في الصفحة—مش وقت كبير، بس برضه له ثمن! بس منين جت الـ 8 عناصر دول؟ الـ CSSOM والـ DOM هي data structures مستقلة! الواضح إن المتصفح مخبي خطوة مهمة وهي الـ(render tree) اللي بتربط بين الـ DOM والـ CSSOM مع بعض إستنوها في المقالة الجاية بإذن الله.