نگاهی به مرورگر وب مدرن (قسمت 3)

Mariko Kosaka

عملکرد درونی یک فرآیند رندر

این قسمت 3 از سری 4 قسمتی وبلاگ است که به نحوه عملکرد مرورگرها می پردازد. قبلاً، معماری چند فرآیندی و جریان ناوبری را پوشش دادیم. در این پست، ما قصد داریم به آنچه در داخل فرآیند رندر رخ می دهد، نگاه کنیم.

فرآیند رندر بسیاری از جنبه های عملکرد وب را لمس می کند. از آنجایی که در فرآیند رندر اتفاقات زیادی می افتد، این پست فقط یک نمای کلی است. اگر می‌خواهید عمیق‌تر کاوش کنید، بخش عملکرد Web Fundamentals منابع بسیار بیشتری دارد.

پردازش های رندر محتویات وب را مدیریت می کنند

فرآیند رندر مسئول هر چیزی است که در داخل یک تب اتفاق می افتد. در یک فرآیند رندر، رشته اصلی بیشتر کدهایی را که برای کاربر ارسال می‌کنید کنترل می‌کند. اگر از وب‌کار یا سرویس‌کار استفاده می‌کنید، گاهی اوقات بخش‌هایی از جاوا اسکریپت شما توسط رشته‌های کارگر مدیریت می‌شود. رشته های کامپوزیتور و شطرنجی نیز در داخل فرآیندهای رندر اجرا می شوند تا یک صفحه را به صورت کارآمد و روان ارائه کنند.

وظیفه اصلی فرآیند رندر تبدیل HTML، CSS و جاوا اسکریپت به یک صفحه وب است که کاربر بتواند با آن تعامل داشته باشد.

فرآیند رندر
شکل 1: فرآیند رندر با یک نخ اصلی، نخ های کارگر، یک رشته ترکیبی و یک رشته شطرنجی در داخل.

تجزیه

ساخت یک DOM

هنگامی که فرآیند رندر یک پیام commit برای ناوبری دریافت می‌کند و شروع به دریافت داده‌های HTML می‌کند، رشته اصلی شروع به تجزیه رشته متن (HTML) و تبدیل آن به یک سند D O Object M odel ( DOM ) می‌کند.

DOM نمایش داخلی یک مرورگر از صفحه و همچنین ساختار داده و API است که توسعه دهنده وب می تواند از طریق جاوا اسکریپت با آن تعامل داشته باشد.

تجزیه یک سند HTML به یک DOM توسط استاندارد HTML تعریف شده است. ممکن است متوجه شده باشید که تغذیه HTML به مرورگر هرگز خطایی ایجاد نمی کند. به عنوان مثال، عدم وجود تگ بستن </p> یک HTML معتبر است. نشانه گذاری اشتباه مانند Hi! <b>I'm <i>Chrome</b>!</i> (برچسب b قبل از تگ i بسته می شود) به گونه ای رفتار می شود که گویی Hi! <b>I'm <i>Chrome</i></b><i>!</i> . این به این دلیل است که مشخصات HTML به گونه ای طراحی شده است که این خطاها را به خوبی مدیریت کند. اگر کنجکاو هستید که این کارها چگونه انجام می شود، می توانید در بخش « مقدمه ای بر مدیریت خطا و موارد عجیب در تجزیه کننده » از مشخصات HTML مطالعه کنید.

بارگیری منابع فرعی

یک وب سایت معمولا از منابع خارجی مانند تصاویر، CSS و جاوا اسکریپت استفاده می کند. این فایل ها باید از شبکه یا حافظه پنهان بارگیری شوند. رشته اصلی می تواند آنها را یکی یکی درخواست کند، زیرا آنها آنها را در حین تجزیه برای ساختن DOM پیدا می کنند، اما به منظور افزایش سرعت، "اسکنر پیش بارگذاری" به طور همزمان اجرا می شود. اگر مواردی مانند <img> یا <link> در سند HTML وجود دارد، اسکنر پیش بارگذاری به نشانه‌های تولید شده توسط تجزیه‌کننده HTML نگاه می‌کند و درخواست‌هایی را به رشته شبکه در فرآیند مرورگر ارسال می‌کند.

DOM
شکل 2: رشته اصلی HTML را تجزیه می کند و یک درخت DOM می سازد

جاوا اسکریپت می تواند تجزیه را مسدود کند

هنگامی که تجزیه کننده HTML یک تگ <script> پیدا می کند، تجزیه سند HTML را متوقف می کند و باید کد جاوا اسکریپت را بارگیری، تجزیه و اجرا کند. چرا؟ زیرا جاوا اسکریپت می تواند شکل سند را با استفاده از چیزهایی مانند document.write() تغییر دهد که کل ساختار DOM را تغییر می دهد ( نمای کلی مدل تجزیه در مشخصات HTML دارای یک نمودار زیبا است). به همین دلیل است که تجزیه کننده HTML باید منتظر بماند تا جاوا اسکریپت اجرا شود تا بتواند تجزیه سند HTML را از سر بگیرد. اگر کنجکاو هستید که در اجرای جاوا اسکریپت چه اتفاقی می افتد، تیم V8 گفتگوها و پست های وبلاگی در این مورد دارد .

به مرورگر راهنمایی کنید که چگونه می خواهید منابع را بارگیری کنید

راه های زیادی وجود دارد که توسعه دهندگان وب می توانند نکاتی را به مرورگر ارسال کنند تا منابع را به خوبی بارگیری کنند. اگر جاوا اسکریپت شما document.write() استفاده نمی کند، می توانید ویژگی async یا defer را به تگ <script> اضافه کنید. سپس مرورگر کد جاوا اسکریپت را به صورت ناهمزمان بارگیری و اجرا می کند و تجزیه را مسدود نمی کند. در صورت مناسب بودن می توانید از ماژول جاوا اسکریپت نیز استفاده کنید. <link rel="preload"> راهی برای اطلاع دادن به مرورگر است که منبع قطعاً برای پیمایش فعلی مورد نیاز است و می‌خواهید در اسرع وقت دانلود کنید. می‌توانید در این مورد در اولویت‌بندی منابع – کمک کردن مرورگر به شما اطلاعات بیشتری کسب کنید.

محاسبه سبک

داشتن یک DOM برای دانستن اینکه صفحه چگونه به نظر می رسد کافی نیست زیرا می توانیم عناصر صفحه را در CSS استایل دهی کنیم. رشته اصلی CSS را تجزیه می کند و سبک محاسبه شده را برای هر گره DOM تعیین می کند. این اطلاعات در مورد نوع سبکی است که بر اساس انتخابگرهای CSS برای هر عنصر اعمال می شود. می توانید این اطلاعات را در بخش computed DevTools مشاهده کنید.

سبک محاسبه شده
شکل 3: رشته اصلی CSS را برای اضافه کردن سبک محاسبه شده تجزیه می کند

حتی اگر هیچ CSS ارائه نکنید، هر گره DOM یک سبک محاسبه شده دارد. تگ <h1> بزرگتر از تگ <h2> نمایش داده می شود و برای هر عنصر حاشیه تعریف می شود. این به این دلیل است که مرورگر دارای یک شیوه نامه پیش فرض است. اگر می‌خواهید بدانید CSS پیش‌فرض کروم چگونه است، می‌توانید کد منبع را اینجا ببینید .

چیدمان

اکنون فرآیند رندر ساختار یک سند و سبک‌های هر گره را می‌داند، اما این برای ارائه یک صفحه کافی نیست. تصور کنید می خواهید نقاشی را از طریق تلفن برای دوست خود توصیف کنید. "یک دایره قرمز بزرگ و یک مربع آبی کوچک وجود دارد" اطلاعات کافی برای دوست شما نیست تا بداند نقاشی دقیقاً چه شکلی است.

بازی دستگاه فکس انسانی
شکل 4: فردی که در مقابل یک تابلوی نقاشی ایستاده است، خط تلفن به شخص دیگر متصل است

چیدمان فرآیندی برای یافتن هندسه عناصر است. رشته اصلی از طریق DOM و سبک های محاسبه شده عبور می کند و درخت طرح بندی را ایجاد می کند که دارای اطلاعاتی مانند مختصات xy و اندازه های جعبه مرزی است. درخت چیدمان ممکن است ساختاری مشابه درخت DOM داشته باشد، اما فقط حاوی اطلاعات مربوط به آنچه در صفحه قابل مشاهده است. اگر display: none اعمال نشود، آن عنصر بخشی از درخت طرح بندی نیست (اما، عنصری با visibility: hidden در درخت طرح بندی وجود دارد). به طور مشابه، اگر یک کلاس شبه با محتوایی مانند p::before{content:"Hi!"} اعمال شود، در درخت layout گنجانده می شود حتی اگر در DOM نباشد.

چیدمان
شکل 5: رشته اصلی که روی درخت DOM با سبک های محاسبه شده می رود و درخت طرح بندی را تولید می کند.
شکل 6: طرح جعبه برای پاراگراف در حال حرکت به دلیل تغییر خط

تعیین چیدمان یک صفحه یک کار چالش برانگیز است. حتی ساده‌ترین طرح‌بندی صفحه، مانند جریان بلوک از بالا به پایین، باید در نظر داشته باشد که فونت چقدر بزرگ است و کجا باید آن‌ها را شکسته کرد، زیرا این موارد بر اندازه و شکل یک پاراگراف تأثیر می‌گذارند. که سپس بر جایی که پاراگراف زیر باید باشد تأثیر می گذارد.

CSS می تواند عنصر را به یک طرف شناور کند، آیتم سرریز را پوشانده و جهت نوشتن را تغییر دهد. می توانید تصور کنید، این مرحله چیدمان کار بزرگی دارد. در کروم، یک تیم کامل از مهندسان روی طرح‌بندی کار می‌کنند. اگر می‌خواهید جزئیات کار آنها را ببینید، صحبت‌های کمی از کنفرانس BlinkOn ضبط شده است و تماشای آن بسیار جالب است.

رنگ کنید

بازی نقاشی
شکل 7: شخصی در جلوی بوم در حالی که قلم مو در دست دارد، به این فکر می کند که ابتدا باید یک دایره بکشد یا مربع

داشتن یک DOM، سبک و طرح‌بندی هنوز برای ارائه یک صفحه کافی نیست. فرض کنید در حال تلاش برای بازتولید یک نقاشی هستید. شما اندازه، شکل و محل عناصر را می دانید، اما هنوز باید قضاوت کنید که آنها را به چه ترتیبی رنگ می کنید.

برای مثال، z-index ممکن است برای عناصر خاصی تنظیم شود، در این صورت رنگ آمیزی به ترتیب عناصر نوشته شده در HTML منجر به رندر نادرست می شود.

z-index شکست
شکل 8: عناصر صفحه به ترتیب نشان‌گذاری HTML ظاهر می‌شوند و در نتیجه تصویر رندر اشتباهی ایجاد می‌شود زیرا z-index در نظر گرفته نشده است.

در این مرحله رنگ، نخ اصلی درخت طرح بندی را برای ایجاد رکوردهای رنگی حرکت می دهد. رکورد رنگ یک یادداشت از فرآیند نقاشی است مانند "ابتدا پس زمینه، سپس متن، سپس مستطیل". اگر روی عنصر <canvas> با استفاده از جاوا اسکریپت کشیده اید، ممکن است این فرآیند برای شما آشنا باشد.

سوابق رنگ
شکل 9: نخ اصلی که از درخت طرح‌بندی عبور می‌کند و رکوردهای رنگ را تولید می‌کند

به روز رسانی خط لوله رندر پرهزینه است

شکل 10: DOM+Style، Layout و Paint درختان به ترتیب تولید

مهمترین چیزی که در رندر خط لوله باید درک کرد این است که در هر مرحله از نتیجه عملیات قبلی برای ایجاد داده های جدید استفاده می شود. به عنوان مثال، اگر چیزی در درخت چیدمان تغییر کند، دستور Paint باید برای بخش‌های آسیب‌دیده سند بازسازی شود.

اگر عناصر را متحرک می کنید، مرورگر باید این عملیات را در بین هر فریم اجرا کند. اکثر نمایشگرهای ما صفحه نمایش را 60 بار در ثانیه (60 فریم در ثانیه) تازه می کنند. هنگامی که در هر فریم در حال جابجایی اشیاء در سراسر صفحه هستید، انیمیشن برای چشم انسان صاف به نظر می رسد. با این حال، اگر انیمیشن فریم های میانی را از دست بدهد، صفحه "جانکی" ظاهر می شود.

jage jank با فریم های از دست رفته
شکل 11: فریم های انیمیشن در یک جدول زمانی

حتی اگر عملیات رندر شما با به‌روزرسانی صفحه مطابقت داشته باشد، این محاسبات در رشته اصلی اجرا می‌شوند، به این معنی که وقتی برنامه شما جاوا اسکریپت را اجرا می‌کند، ممکن است مسدود شود.

jage jank توسط جاوا اسکریپت
شکل 12: فریم های انیمیشن در یک جدول زمانی، اما یک فریم توسط جاوا اسکریپت مسدود شده است.

می توانید عملیات جاوا اسکریپت را به تکه های کوچک تقسیم کنید و با استفاده از requestAnimationFrame() برای اجرا در هر فریم برنامه ریزی کنید. برای اطلاعات بیشتر در مورد این موضوع، لطفاً به بهینه سازی اجرای جاوا اسکریپت مراجعه کنید. همچنین ممکن است جاوا اسکریپت خود را در Web Workers اجرا کنید تا از مسدود کردن رشته اصلی جلوگیری کنید.

درخواست قاب انیمیشن
شکل 13: تکه های کوچکتر جاوا اسکریپت در حال اجرا بر روی خط زمانی با قاب انیمیشن

ترکیب کردن

چگونه یک صفحه را ترسیم می کنید؟

شکل 14: انیمیشن فرآیند شطرنجی ساده

اکنون که مرورگر ساختار سند، سبک هر عنصر، هندسه صفحه و ترتیب رنگ را می داند، چگونه یک صفحه را ترسیم می کند؟ تبدیل این اطلاعات به پیکسل در صفحه نمایش شطرنجی نامیده می شود.

شاید یک راه ساده برای رسیدگی به این موضوع، شطرنجی کردن قسمت‌های شطرنجی داخل نما باشد. اگر کاربر صفحه را اسکرول کرد، قاب شطرنجی را جابجا کرده و با شطرنجی بیشتر قسمت های از دست رفته را پر کنید. زمانی که کروم برای اولین بار منتشر شد، شطرنجی‌سازی را به این شکل انجام داد. با این حال، مرورگر مدرن فرآیند پیچیده تری به نام ترکیب بندی را اجرا می کند.

کامپوزیت چیست

شکل 15: انیمیشن فرآیند ترکیب

کامپوزیت تکنیکی است برای جدا کردن بخش‌های صفحه به لایه‌ها، شطرنجی کردن آن‌ها به طور جداگانه و ترکیب به عنوان یک صفحه در یک رشته مجزا به نام رشته ترکیبی. اگر اسکرول اتفاق بیفتد، از آنجایی که لایه‌ها قبلاً شطرنجی شده‌اند، تنها کاری که باید انجام دهید این است که یک فریم جدید را ترکیب کنید. با جابجایی لایه ها و ترکیب یک فریم جدید می توان انیمیشن را به همین روش به دست آورد.

با استفاده از پنل لایه ها می توانید ببینید که چگونه وب سایت شما در DevTools به لایه ها تقسیم شده است.

تقسیم به لایه ها

برای اینکه بفهمیم کدام عناصر باید در کدام لایه ها باشند، رشته اصلی از درخت layout عبور می کند تا درخت لایه ایجاد شود (این قسمت در پنل عملکرد DevTools "Update Layer Tree" نامیده می شود). اگر بخش‌های خاصی از صفحه که باید لایه جداگانه باشند (مانند منوی کناری اسلاید) یکی نمی‌شوند، می‌توانید با استفاده از ویژگی will-change در CSS به مرورگر اشاره کنید.

درخت لایه
شکل 16: نخ اصلی در حال عبور از درخت طرح بندی درخت لایه تولید می کند

ممکن است وسوسه شوید که به هر عنصر لایه بدهید، اما ترکیب بیش از حد لایه ها می تواند منجر به عملکرد کندتر از شطرنجی کردن بخش های کوچک صفحه در هر فریم شود، بنابراین بسیار مهم است که عملکرد رندر برنامه خود را اندازه گیری کنید. برای اطلاعات بیشتر در مورد موضوع، به ویژگی‌های فقط Compositor و مدیریت تعداد لایه‌ها نگاه کنید.

رستر و کامپوزیت خارج از موضوع اصلی

هنگامی که درخت لایه ایجاد شد و ترتیب رنگ ها مشخص شد، نخ اصلی آن اطلاعات را به رشته کامپوزیتور متعهد می کند. سپس رشته کامپوزیتور هر لایه را شطرنجی می کند. یک لایه می تواند مانند طول کل یک صفحه بزرگ باشد، بنابراین رشته ترکیب آنها را به کاشی ها تقسیم می کند و هر کاشی را به رشته های شطرنجی می فرستد. رشته های شطرنجی هر کاشی را شطرنجی می کنند و در حافظه GPU ذخیره می کنند.

شطرنجی
شکل 17: رشته های شطرنجی نقشه بیت کاشی ها را ایجاد می کنند و به GPU ارسال می کنند.

رشته ترکیب‌کننده می‌تواند رشته‌های شطرنجی مختلف را اولویت‌بندی کند تا چیزهایی که در ویوپورت (یا نزدیک) هستند، بتوانند ابتدا شطرنجی شوند. یک لایه همچنین دارای چندین کاشی کاری برای رزولوشن های مختلف برای رسیدگی به مواردی مانند عمل بزرگنمایی است.

هنگامی که کاشی‌ها شطرنجی می‌شوند، رشته Compositor اطلاعات کاشی به نام draw quads را برای ایجاد یک قاب ترکیبی جمع‌آوری می‌کند.

چهارتایی بکش حاوی اطلاعاتی مانند مکان کاشی در حافظه و مکان صفحه برای ترسیم کاشی با در نظر گرفتن ترکیب صفحه.
قاب آهنگساز مجموعه ای از چهارتایی ترسیم که نشان دهنده یک فریم از یک صفحه است.

سپس یک فریم کامپوزیتور از طریق IPC به فرآیند مرورگر ارسال می شود. در این مرحله، یک فریم ترکیب‌کننده دیگر می‌تواند از رشته UI برای تغییر رابط کاربری مرورگر یا از سایر فرآیندهای رندر برای برنامه‌های افزودنی اضافه شود. این فریم های کامپوزیتور به GPU فرستاده می شوند تا روی صفحه نمایش داده شوند. اگر یک رویداد اسکرول وارد شود، رشته کامپوزیتور یک فریم کامپوزیتور دیگری ایجاد می کند تا به GPU ارسال شود.

ترکیب کردن
شکل 18: نخ کامپوزیتور ایجاد قاب ترکیبی. فریم به فرآیند مرورگر و سپس به GPU ارسال می شود

مزیت کامپوزیت این است که بدون درگیر کردن نخ اصلی انجام می شود. نخ Compositor نیازی به انتظار برای محاسبه سبک یا اجرای جاوا اسکریپت ندارد. به همین دلیل است که ترکیب کردن فقط انیمیشن ها برای عملکرد روان بهترین در نظر گرفته می شود. اگر طرح یا رنگ باید دوباره محاسبه شود، نخ اصلی باید درگیر شود.

بسته شدن

در این پست، ما به رندر خط لوله از تجزیه به ترکیب نگاه کردیم. امیدواریم اکنون این اختیار را داشته باشید که در مورد بهینه سازی عملکرد یک وب سایت بیشتر بخوانید.

در پست بعدی و آخرین این مجموعه، ما به موضوع compositor با جزئیات بیشتری نگاه خواهیم کرد و خواهیم دید که وقتی ورودی کاربر مانند mouse move و click ماوس وارد می شود، چه اتفاقی می افتد.

آیا از پست لذت بردید؟ اگر سؤال یا پیشنهادی برای پست آینده دارید، مایلم در بخش نظرات زیر یا @kosamari در توییتر از شما بشنوم.

بعدی: ورودی به کامپوزیتور می رسد