مرورگرها مهم ترین نقش رو در دنیای انتقال اطلاعات امروز ایفا می کنند و هرچقدر زمان بیشتری میگذره با پیشرفته تر شدن مرورگرها می تونن کارهایی رو انجام بدن که بیشتر به وجد بیایم ! امروز هم تصمیم گرفتم باهم از تاریخچه و چگونگی نمایش یک سایت در مرورگر ( بدون وابستگی به نوع مرورگر ) صحبت کنیم.
خیلی خودمونی تصمیم گرفتم مطالبی رو بگم که توی وب فارسی در موردش کمتر کار شده باشه و دربرگیرنده ی مسائل پایه ای باشه.
سعی می کنم که کوتاه تر، جذاب تر و با لحن صمیمی تری بنویسم تا خسته نشید.
لیست مطالبی که قراره در این مقاله باهاش صحبت کنیم :
و در انتها بگم این مقاله بالاخره باعث میشه که مباحث دانشگاه یکم به دردتون بخوره :دي
برای همه ی مرورگر ها می تونیم معماری زیر رو در نظر بگیریم :
معرفی User Interface : خب این User Interface ها همون interaction هایی هستن که کاربر با مرورگر داره. به عنوان مثال دکمه ی back ، دکمه ی refresh ، آدرس بار و...
معرفی Browser Engine : موتور هر مرورگر نقش واسطه ای میان موتور رندر و عملیات درخواستی کاربر رو داره. به عبارت دیگه وقتی کاربر روی دکمه ی refresh کلیک میکنه وظیفه ی Browser Engine شروع میشه و این عملیات رو برای موتور رندر قابل فهم میکنه تا عملیات refresh صورت بگیره.
معرفی Rendering Engine : وظیفه ی این قسمت تولید Render Tree و سپس نمایش صفحه هست که در ادامه مفصل در موردش صحبت خواهیم کرد.
معرفی Networking : این بخش همونطور که مشخص هست وظیفه ی ارتباط با شبکه و Network و همچنین فرآیند DNS Lookup رو بر عهده داره که باز هم در ادامه در موردش صحبت خواهیم کرد.
معرفی Javascript Interpreter : این بخش نیز وظیفه ی Parse کردن کدهای جاوا اسکریپت برای مرورگر رو بر عهده داره.
معرفی Ui Backend : دکمه های هر مرورگر در پنجره ی مربوط به خودش در هر سیستم عامل مختلفه و ظاهر متفاوتی داره همینطور نمایش یک input ساده در سیستم عامل مک تفاوت ظاهری بسیاری با نمایش همان input در سیستم عامل ویندوز داره و این دقیقا همان تعریف Ui Backend هست که با توجه به سیستم عامل کاربر قابل تعریف هست.
معرفی Data persistence : بخش هایی مثل کوکی و Web Storage ها در این قسمت قرار دارند.
خب مرورگر های مختلف Rendering Engine های مختلفی هم دارند که در زیر توفیق آشنایی باهاشون نصیبمون میشه.
گوگل کروم : ابتدا از WebKit استفاده می کرد اما بعد ها تصمیم گرفت که از این موتور یک fork بگیره و موتور دلخواه خودش با نام Blink رو بسازه.
موزیلا : از موتوری به نام Gecko استفاده می کنه.
سافاری : از موتوری که توسط خود شرکت اپل توسعه داده میشه به نام WebKit استفاده می کنه.
اوپرا : این مرورگر کلا Chrome Base هست.
و اما Microsoft Edge : این مرورگر هم re build میشه روی Chromium و در نتیجه از موتور Blink استفاده می کنه.
تا حالا فکر کردید وقتی آدرس یک سایت رو می زنید چه عواملی اون پشت زحمت می کشند که سایت به شما نمایش داده بشه؟ از این قسمت به بعد قراره که این عوامل پشت صحنه رو معرفی کنیم و در نهایت از خانواده ی آقای رجبی هم تشکر کنیم.
خب هر سایت یک شناسنامه داره و مرورگر ها مثل ما نمیفهمن که google.com یعنی چی ! چون از ضریب هوشی پایین تری برخوردار هستند فقط آدرس IP رو متوجه میشن. خب پس چی میشه که شما با وارد کردن google.com توی آدرس بار مرورگر به اون سایت دسترسی پیدا می کنید؟
اینجا مرورگر شما یک مسیری رو طی می کنه که به ترتیب شامل مراحل زیره :
1- اول دنبال آی پی آدرسی که شما وارد کردید در کش خودش می گرده
2- اگر پیدا نکنه به آقای سیستم عامل میگه شما نمیدونی آی پی این آدرس چیه؟
3- اگر اونم ندونه میره سراغ recursive resolver در سیستم عامل تا کش رو بررسی کنه و ببینه قبلا هیچ احد الناسی نخواسته بره این سایت؟ ( که این resolver رو میتونه ISP به شما بده و یا خودتون ست کنید و یا اپلیکیشن های دیگه ست کرده باشند )
4- در صورتی که هنوز پیدا نکرده باشه چمدوناشو می بنده و میره سراغ root server تا به TLD برسه. در این جا باید بدونید که هر کدوم از دامنه ها ( com،net،org،ir و .. ) توسط Top Level Domain کنترل می شن که کلا 13 تا Root Servers داریم و خب هدف از این قسمت اینه که بتونه TLD Server مدنظر خودش رو پیدا کنه تا به name server هاش دسترسی داشته باشه. ( اگه بخوام ساده تر بگم اینجا میره و دنبال TLD دامنه com می گرده )
5- اینجا میره به TLD میگه شما google.com می شناسید؟ من رو root server فرستاده و اون هم با بررسی name server هاش متوجه میشه که فرضا یک ns1.google.com ثبت شده و خب این مقدار یک ip متناظر داره که همون آی پی name server گوگل هست و به مرورگر ما میده و میگه بفرمایید لطفا رسیدشم امضا کنید.
6- مرورگر ما با اولین پرواز برمیگرده به خونه اش و حالا به اون IP مد نظر یک request می زنه.
پ.ن : این داستان کوتاه یک برداشت آزاد از سایت howdns.works بود.
خب HTTP یک کلاینت - سرور پروتکل هست. این به این معنیه که اصولا یک ریکوئست از طرف یک user agent ( که اغلب مرورگر هست ولی می تونه فقط مرورگر نباشه ( مثلا crawler باشه )) به سمت سرور ارسال میشه و سرور هم یک ریسپانس یا پاسخ به این درخواست می فرسته.
زمانی که مرورگر ما آدرس IP سایت مورد نظر رو پیدا کرد توسط یک ارتباط TCP 3 way تلاش می کنه به سرور متصل بشه در این نوع ارتباط ابتدا لازمه که درستی و صحت ارتباط تایید بشه پس در 3 مرحله این اتفاق صورت می گیره ابتدا مرورگر یک درخواست SYNchronize می فرسته و وقتی سرور این packet رو دریافت کرد به مبدا با استفاده از یک Synchronization Acknowledge Packet پاسخ میده و در نهایت از سمت مبدا Acknowledge Packet به سمت سرور ارسال میشه که میگه بسته ای که فرستادی رسید !
حالا شما در فرآیند بالا مبدا رو مرورگر در نظر بگیرید و مقصد رو یک وب سرور
که البته امروزه چون از پروتکل HTTPS استفاده میشه پس یک بخش دیگه اضافه میشه به این صورت که سرور سرتیفیکیت TLS خودش رو برای کلاینت می فرسته و کلاینت هم ابتدا توسط یک جفت Key عملیات احراز هویت رو انجام میده و پس از اون هم یک symmetrically key می سازند. ( بخاطر وجود همین یک فرآیند اضافه تر هست که میگن HTTPS از HTTP کندتر هست اما خب این کند بودن به اون میزانی نیست که شما احساسش کنید و همچنین مزایایی که داره خیلی بیشتر هست )
پس از برقراری یک اتصال بین کلاینت و سرور، از سمت سرور یک Response به سمت کلاینت ارسال میشه که یک سند مبتنی بر HTML هست. به زمانی که طول میکشه تا اولین دیتا برای ریکوئست اولیه ارسال بشه میگن Time To First Byte یا به صورت اختصار TTFB که این دیتا طی قانون 14kb ارسال میشه بدین صورت که ابتدا 14kb از سند ارسال میشه (1460 بایت) و سپس این میزان دو برابر میشه تا به پهنای باند کاربر برسه.
زمانی که مرورگر اولین بسته از دیتاها رو دریافت می کنه شروع می کنه به Parse کردن و این فرآیند به این معنیه که ما میخوایم DOM و CSSOM رو بسازیم تا به مراحل رندرینگ و Paint برسیم.
حالا به مباحث شیرین دانشگاهی می رسیم اگر رشتتون نرم افزار باشه و کامپایلر پاس کرده باشید می دونید که در علم کامپیوتر Parse کردن به معنای تقسیم عبارات ورودی را به بخش هاییه که برای کامپیوتر مفید باشند همچنین وظیفه ی دیگه ی Parser اینه که دیتای ورودی که دنباله ای از توکن هاست رو بگیره و تعیین کنه که آیا این عبارت می تونه به وسیله ی گرامر زبان مورد نظر تولید بشه یا نه.
اولین مرحله ی Parse کردن HTML ، تحلیل واژگان یا Lexicon هست. همونطور که می تونید واژگان HTML شامل موارد زیر هست :
زمانی که یک سند HTML در حال Parse شدن هست عبارات اون توسط Finite-state machine میان و توکن ها رو تشخیص میدن. توکن ها حاوی همین مقادیری هستند که بالاتر لیست شده ( تگ شروع و پایان ، attribute name ها و مقادیر اون ها ) و اگر اون فایل HTML درست نوشته شده باشه، تجزیه کننده اون نشانه گذاری هایی رو که انجام داده توسط توکن ها درون داکیومنت قرار میده !
زمانی که HTML تجزیه شد DOM Tree ساخته میشه ! اما اشتباه نکنید همه ی HTML تجزیه شده ی ما DOM Tree رو شامل نمیشه بلکه ممکنه چیزهایی در HTML ما وجود داشته باشه که در DOM ما وجود نداشته باشه.
در عکس زیر نمای یک DOM Tree رو می بینید :
دومین مرحله Parse کردن CSS هست که منجر به ساخت CSSOM Tree میشه. فرآیند Parse کردن CSS تقریبا سر راست تر است ( نسبت به HTML ) که وارد این مقوله نمیشیم ولی بخش منابع رو مطالعه بفرمایید. ساختن CSSOM Tree بسیار بسیار سریع انجام میگیره.
در عکس زیر نمای یک CSSOM Tree رو می بینید:
پردازش های دیگر :
به گفته ی Tali Garsiel مدل وب یک مدل همزمانی و sync هست.
پس زمانی که داره CSSOM Tree ساخته میشه assest هایی مثل فایل های جاوا اسکریپت دانلود میشن ( با تشکر از preload scanner )
همچنین در این مرحله مرورگر یک accessibility tree هم می سازه که ورژن هوشمند و همروند DOM هست که یک Experimantal Javascript API هم براش داریم که باز هم در منابع می تونید بیشتر ازش بخونید.
در مرحله ی قبل CSSOM Tree و DOM Tree ساخته شدند و با استفاده از این دو ما میتونیم Render Tree رو بسازیم تا بتونیم layout موردنظرمون ( آن چیز هایی که قابل دیدن هستند ) رو بسازیم.
پس خیلی طبیعیه که گزاره ی DOM Tree === Render Tree همیشه درست نیست و گاها چیزهایی در DOM Tree وجود دارند که visible نیستند. ( همچنین تگ هایی که display:none شدند هم در Render Tree وجود ندارند اما تگ هایی که visibility: hidden شدند در Render Tree قرار می گیرند)
این مرحله اختصارا Style نامیده میشه و حالا میخوایم به سراغ مرحله ی Layout بریم.
در مرحله ی Style مرورگر مشخص کرده که چه node هایی قراره نمایش داده بشن ( حتی اگه invisible باشند )
اما در مرحله ی Layout اندازه ی طول عرض و همچنین جایگاه هر node ای که در Render Tree مشخص شده تعیین میشه و به تکرار این مرحله در دفعات بعدی میگن Reflow !
در این مرحله مرورگر تمام layout هایی که در مرحله ی قبلی محاسبه شده بودند رو به صورت پیکسل های واقعی روی صفحه نمایش نشون میده. این مرحله از اون چیزی که فکر می کنید بسیار سریع تر انجام میشه پس احتمالا برای پرفومنس سایتتون جزو اولویت های اولیه می تونه نباشه. و به انجام دوباره ی این فرآیند میگن Repaint !
خب تبریک میگم سایت آماده ی نمایشه و تمام اجزایی که در مراحل قبلی به Render Tree پیوستند و سپس با Style مشخص شدند و با Layout بندی از جایگاه خودشون باخبر شدن و در نهایت با Paint رنگ آمیزی شدند و به پیکسل های قابل نمایش درومدند در این مرحله باهم ترکیب میشن و هر بار که لازم باشه این فرآیند ها تکرار بشن ما Reflow و Repaint و Re-composite رو خواهیم داشت.
هر ریکوئستی به سمت وب سرور با یک درخواست HTTP شروع میشه سپس از سمت سرور یک response حاوی دیتا و مقادیری مانند header ارسال میشه. مرورگر شروع به Parse کردن HTML می کنه و با استفاده از اون DOM Tree رو میسازه . اصولا در ریکوئست اولیه تعدادی منابع خارجی یا External resource هم پیدا میکنه که بعضی هاشون خاصیت بلاک رو دارند یعنی Parse کردن HTML رو تا زمانی که اون فایل موردنظر هندل نشه متوقف می کنند و بعضی از این External Resource ها هم خاصیت none Blocking دارند. بعد از این اتفاقات به شکل مشابه CSSOM Tree ساخته میشه و از ترکیب این دو Render Tree بوجود میاد که با استفاده از Style دهی ابتدا مشخص می کنه چه node های قابل نمایشی داریم و سپس با layout بندی جایگاه و اندازه ی هر node رو تعیین می کنه و در مرحله ی paint اون ها رو به پیکسل هایی قابل نمایش در میاره.
در انتهای مقاله باید تشکر کنم از دوست عزیزم بهنام علیزاده که با دلسوزی متن من رو خوندن و اشکالات علمی رو بهم متذکر شدند و باعث شدند که من اصلاحشون کنم تا مقاله ی بهتری داشته باشیم.
امیدوارم شما هم تو زندگیتون یه بهنام علیزاده داشته باشید که علمشو رایگان در اختیارتون بزاره. ?
ممنونم که این مقاله رو مطالعه کردید در قسمت نظرات به سوالاتتون پاسخ میدم.
تا مقاله ی بعد زکات علم رو فراموش نکنید.
من در شبکه های اجتماعی :
منابع مفید برای مطالعه ی بیشتر :