Rendering In Browser

Wai Lin Kyaw
4 min readJan 20, 2021

Rendering ဆိုတာက web page တွေရဲ့ HTML, CSS နဲ့ JavaScript တွေကို Screen ပေါ်မှာ မြင်ရဖို့ browser ကနေလုပ်ပေးရတဲ့ အပိုင်းပါ။ browser တွေက အစုံရှိတော့ တစ်ခုနဲ့ တစ်ခု ကွဲတာတွေလည်း ရှိမှာပါ။ ဒီမှာတော့ Chrome ကိုပဲ အဓိကထား ပြောပါမယ်။ အလုပ်လုပ်ပုံတွေ သိထားရင် တခြား browser တွေအတွက်လည်း မခက်ခဲတော့ပါဘူး။

Browser ထဲမှာက Process တွေခွဲပြီး အလုပ်လုပ်တယ်။ ဥပမာ Plugin Process တို့ Network Process တို့ စသည်ဖြင့်။ Browser Process ဆိုတဲ့ Main Process တစ်ခုရှိတယ်။ သူကနေမှ နောက်ထပ်လိုတဲ့ Process တွေထပ်ထပ်ခွဲတယ်၊ လိုအပ်သလို handle လုပ်တယ်။ Rendering အတွက်ကျတော့ ဖြစ်နိုင်မယ်ဆိုရင် browser tab တစ်ခုကို process တစ်ခုစီပေးတယ်။ Renderer process လို့ခေါ်တယ်။ rendering နဲ့ ပက်သက်တာတွေကို အဲ့ဒီ process အတွင်းမှာပဲ အလုပ်လုပ်ဆိုတဲ့ သဘော။

chrome 67 လောက်မှာ iframe တစ်ခုချင်းစီကိုပါ process သပ်သပ်ခွဲပေးလိုက်တယ်၊ ဘာလို့လဲဆိုတော့ site a ကို site b မှာ လာပြီး iframe နဲ့ embedded လုပ်တယ်ဆိုပါစို့။ tab တစ်ခုချင်းစီကို process တစ်ခုပေးထားမယ်ဆိုရင် site a နဲ့ site b က renderer process တစ်ခုတည်းအောက်ရောက်သွားမယ်၊ memory space ကို site နှစ်ခုကနေ share လုပ်သုံးရမယ်။ ဒီအထိလည်း အဆင်ပြေနေသေးတယ်။ ဒါပေမဲ့ Same Origin Policy လိုမျိုး web security ပိုင်းက ကြည့်ရင် site တစ်ခုရဲ့ data ကို နောက်တစ်ခုက ခွင့်ပြုချက်မရပဲ ယူသုံးခွင့်မရှိအောင် ထိန်းရတယ်။ ဒါကြောင့် process သပ်သပ် ခွဲထုတ်လိုက်ရတာ။ Renderer Process က site တစ်ခုအတွင်း ဘယ်လို display လုပ်ရမလဲဆိုတဲ့ အပိုင်းကို တာ၀န်ယူတယ်။

အနည်းဆုံးတော့ tab တစ်ခု ( site ) ချင်းစီမှာ renderer process တစ်ခုစီရှိတော့ site တစ်ခုက တစ်နေရာရာမှာ block ဖြစ်ပြီး UI လည်း update မလုပ်နိုင်ဖြစ်ပြီး not responding ဖြစ်လာပြီဆိုရင် အဲ့ tab တစ်ခုပဲ ရပ်သွားပြီး ကျန်တဲ့ tab တွေကတော့ ဆက်သုံးလို့ရနေဦးမှာပါ။

အဲ့တော့ site တစ်ခုရဲ့ address url ကို browser မှာ ရိုက်လိုက်ပြီဆိုတာနဲ့ browser process ရဲ့ network thread ကနေ လုပ်စရာရှိတာလုပ်မယ်၊ Render လုပ်ဖို့လိုတယ်ဆိုရင် UI thread ( Renderer process နဲ့မဆိုင်ဘူး သူက Browser က new tab ဖွင့်လိုက်တာနဲ့ url bar တို့၊ တစ်ခုခု ရိုက်လိုက်ရင် url လား search query လားသိအောင် url parsing တွေ၊ တခြားမြင်နေရတာတွေကို handle လုပ်ပေးတဲ့ကောင် ) ကနေ Renderer Process တစ်ခု initialize လုပ်မယ်။ ဒီအချိန်မှာ network request ကနေ response အကုန်မရသေးဘူး။ Render Process ကို initialize လုပ်တာနဲ့ network request နဲ့ parallel သွားနေမှာ။ response အကုန်ရမှ render process ကို initialize စလုပ်တာ မဟုတ်ပါဘူး။ HTML လိုကောင်မျိုးဆိုရင် render လုပ်ဖို့လိုမယ် ဒီတော့ render process ကို စထားမယ်။ zip file လိုမျိုးဆိုရင် render process မလိုဘူး။

Data လည်းရပြီ Renderer process လည်း ready ဖြစ်ပြီဆိုရင် Browser Process ကနေ Renderer Process ကို data လှမ်းပေးပြီး Render လုပ်ဖို့ပြောမယ်။ Renderer Process ကနေ data တွေရပြီဆိုရင် navigation ပြီးသွားပြီလို့ပြောလို့ရတယ်။ document ထဲမှာ ဘာတွေပါလဲပါဆက်ကြည့်ဖို့ပဲ လိုတော့တယ်။ Rendering တကယ်အလုပ်လုပ်မှာက ဒီနေရာမှ စမှာပါ။

DOM

အဲ့တော့ Renderer Process က ဘာတွေလုပ်မလဲ။ အရင်ဆုံး HTML ကို parse လုပ်ပြီး Document Object Model ဆောက်မယ်။ ဒီအဆင့်မှာ အရင်ဆုံး bytes တွေကို characters ပြောင်းမယ်။ ပြီးရင် characters တွေကို HTML specification တွေနဲ့ အညီ tokenize လုပ်ပစ်တယ်။ token တစ်ခုစီတိုင်းမှာ သက်ဆိုင်ရာ rules တွေ သတ်မှတ်ချက်တွေ ရှိတယ်။ တစ်ခါတစ်လေ elements တွေကို tag အဖွင့်ပါပြီး အပိတ်မပါဘဲ ရေးပေမဲ့ အလုပ်လုပ်တာတွေ့ဖူးမှာပါ။ HTML spec က ဒီလို Error တွေကို cover ဖြစ်အောင် handle လုပ်ဖို့ပြောထားတာကြောင့်ပါ။

နောက်တစ်ဆင့်က ရလာတဲ့ token တစ်ခုချင်းနဲ့ သက်ဆိုင်တဲ့ properties တွေ rules တွေသုံးပြီး object ( node ) လေးတွေဆောက်ပါတယ်။ HTML markup ထဲမှာ external stylesheet တွေ scripts ( JS ) တွေနောက် images တွေလည်းပါမှာပါ။ JavaScript က HTML parsing ကို block လုပ်တယ်။ ဘာလို့လဲဆိုတော့ JavaScript ကနေ document ကို side effect တွေဖြစ်စေနိုင်လို့ ဥပမာ document.write() တို့လိုမျိုး။

ဒီ lexing အဆင့် ပြီးသွားရင်တော့ ရလာတဲ့ nodes တွေကို tree structure နဲ့ HTML Markup ပေါ်မူတည်ပြီး parent-child relationships တွေသတ်မှတ်ပါတယ်။ HTML Parse လုပ်တာ ဘယ်လောက်ကြာလဲ chrome ထဲမှာ ကြည့်လို့ရပါတယ်။ HTML elements တွေများလေလေ Parse time ပိုကြာလေလေဖြစ်မှာပါ။ တစ်ချို့တွေရှိတယ် div -> div -> div…, element လေးတစ်ခုပြချင်တာကို မပြီးဆုံးနိုင်တဲ့ div အထပ်ထပ်နဲ့ wrap လုပ်ကြတာပါ။ မလိုအပ်ပဲနဲ့ elements တွေအများကြီး သုံးမိနေပြီဆိုရင် Parse Time က လိုတာထက် ပိုကြာမယ်ဆိုတာ သတိရပါ။ Performance တွေ ဂရုမစိုက်ဘူး ဆိုရင်တော့လည်း သဘောပေါ့။

CSSOM

ဒုတိယ အဆင့်အနေနဲ့ CSS rules တွေ ကို parse လုပ်ပြီး browser ကသူနားလည်တဲ့ CSSOM ( CSS Object Model ) ဆောက်တယ်။ steps တွေကတော့ HTML မှာတုန်းကလိုပဲ bytes -> characters -> tokens -> nodes -> CSSOM ပေါ့။ တစ်ခုသိထားရမှာက CSSOM က DOM နဲ့မသက်ဆိုင်သေးဘူး။ CSS rules တွေကို tree အနေနဲ့ဆောက်လိုက်တာ။ ဘာလို့ tree structure သုံးရတာလဲဆိုတော့ ဥပမာ body ကို CSS property တစ်ခုခု ( font-size: 16px ) ပေးလိုက်ရင် body ကို apply လုပ်မယ် ပြီးရင် child တွေရဲ့ style ကိုပါ general rule အနေနဲ့ apply လုပ်ဖို့လိုတယ်။ ဆိုလိုတာက body က font size 16px ပေးထားမယ်ဆို body ထဲမှာ paragraph တစ်ခုပါရင် အဲ့ကောင်ရဲ့ font size ကလည်း 16px ဖြစ်ဖို့လိုတယ်။ ဒီတော့ tree structure သုံးမှပဲ recursively ပြန်ပြီး style compute လုပ်လို့ရမယ်။ browser တွေရဲ့ default style ကလည်း CSSOM ထဲမှာတစ်ခါတည်းပါမယ်။

Render Tree

DOM ရော CSSOM ရောရပြီဆိုရင် သပ်သပ်စီဖြစ်နေတဲ့ သူတို့နှစ်ခုကို actual rendering လုပ်နိုင်ဖို့ tree နှစ်ခုကို merge လုပ်ပေးဖို့လိုတယ်။ ဒီအဆင့်မှာ render လုပ်ဖို့လိုတဲ့ screen ပေါ်မှာ မြင်ရမဲ့ ကောင်တွေကိုပဲရွေးထုတ်ပြီး tree ဆောက်မှာ။ DOM မှာဆိုရင် head တို့ meta တို့ ပါပေမဲ့ screen ပေါ်မှာ ပြမှာမဟုတ်တဲ့ အတွက်ချန်ခဲ့မယ်။ နောက် visible မဖြစ်တဲ့ elements တွေ ဥပမာ CSSOM ကနေ display:none ပေးထားတဲ့ elements တွေချန်ခဲ့မယ်။ visible ဖြစ်သမျှ node တိုင်းအတွက် CSSOM ကနေ match ဖြစ်တဲ့ CSS rules တွေ apply လုပ်မယ်။ ဒီကနေရလာမှာက computed styles တွေ။ browser တွေမှာ computed styles တွေကြည့်လို့ရအောင် လုပ်ပေးထားတာများပါတယ်။

Layouting ( Reflow )

Render tree ရပြီဆိုရင် ပြချင်တဲ့ကောင်တွေရပြီဆိုတော့ Layout ချဖို့လိုတယ်။ elements တွေရဲ့ size တွေ၊ device ရဲ့ viewport ပေါ်မူတည်ပြီး coordinates ဘယ်လောက်မှာ ထားရမလဲ ဆိုတာတွေ တွက်ရတယ်။ ရိုးရိုးတန်းတန်း page လေးတွေမှာတောင် element ရဲ့ size တွက်ချင်တယ်ဆိုရင် သူ့ထဲက font size တွေ line breaks တွေကိုပါထည့်တွက်ရမှာပါ။ ဒီတော့ layout တွက်တဲ့ step မှာက တော်တော်ကို cost များပါတယ်။ layout တွက်ပြီးသွားရင် element တွေရဲ့ box model ဆိုတာရလာတယ်။ box model မှာ element တစ်ခုချင်းစီရဲ့ size တွေ position တွေ အတိအကျရလာမယ်။

Painting

Layout ချပြီးရလာတဲ့ box တွေ element ရဲ့ text contents တွေ style တွေကို ကြည့်ပြီး screen ပေါ်မှာ ပြရမဲ့ pixel တွေအဖြစ်ပြောင်းတယ်။ ပြောင်းပြီးရင် Layers တွေ ပေါ်တင်တယ်။ Layer ကတစ်ခုတည်း ဖြစ်ချင်မှ ဖြစ်မယ်။ Painting မလုပ်ခင် Layer Tree Create လုပ်တဲ့ step တစ်ခုရှိတယ်။ သူက web page မှာ ခဏခဏ ပြောင်းနေရမဲ့ elements တွေ အပိုင်းတွေ ( ဥပမာ css transform သုံးထားတာမျိုး ) ပါလား ကြည့်ပြီး လိုအပ်တဲ့ Layer တွေ create လုပ်ထားလိုက်မှာ။ ဒီ Painting step ‌ရောက်တော့မှ pixel ပြောင်းပြီး ထွက်လာတဲ့ rasterized elements တွေကို Layer တွေပေါ်ပြန်တင်တာပါ။

Compositing

ဒါကတော့ ရလာတဲ့ Layer တွေကို သူ့နေရာနဲ့သူနေရာချပြီး frame တစ်ခု ‌ဆောက်မယ်ပြီးရင် screen ပေါ်တင်ပေးမယ်ပေါ့။ နောက် scroll လုပ်တာတို့ animation ( transform လိုကောင်မျိုးနဲ့ ) တို့ဆိုရင် frame အသစ်တွေ တန်းစီ ဆောက်မယ်။ screen ပေါ်ပြန်တင်မယ်ပေါ့။ ဒီကောင်ကျတော့ Layer တွေကိုပဲ ပြန် change ပြီး frame အသစ်‌ဆောက်တာပေါ့။

Rendering Pipeline

အပေါ်မှာ ပြောခဲ့တဲ့ steps တွေထဲမှာ တစ်ခုခုကို သွားပြင်ရင် screen ပေါ်မှာ ပြန်ပြနိုင်ဖို့ သူ့နောက်က steps တွေကို ထပ်လုပ်ရတယ်။ Reflow — css ကနေ display ကို ပြောင်းလိုက်တာတို့ element အသစ်ထပ်ထည့်တာတို့ element ရဲ့ size ကိုသုံးပြီး animate လုပ်တာတို့ဆိုရင် browser ကနေ elements တွေရဲ့ position နဲ့ size တွေ ( layout ) ကို ပြန်တွက်ရတယ်။ တွက်ပြီးရင် နောက်ကလိုတဲ့ steps တွေကိုပါ ထပ်လုပ်ရတယ်။ Repaints — background color တို့ box-shadow တွေ ပြောင်းတာမျိုးဆိုရင် repaint လုပ်ရတယ်၊ ပြီးရင် compositing ပါထပ်လုပ်ရတယ်။

အပေါ်ကဟာတွေ အကုန်သိထားရင်တော့ DOM ကိုတိုက်ရိုက်ပြင်တာ ဘာလို့ cost များလဲ၊ performance ထိလဲ နားလည်နိုင်မယ်။ ပြင်စရာရှိတယ်ဆိုရင်တောင် ခဏခဏ ပြင်မဲ့အစား batch အလိုက်စုပြင်တာကောင်းတယ်။ ဒါဆို React.JS ကဘာတွေ ကောင်းတာလဲ မြင်သွားမှာပါ။ နောက် animation တွေလုပ်တဲ့အခါမှာ element ရဲ့ size ကိုတိုက်ရိုက် change တာမျိုး position တွေ ပြောင်းချင်ရင် Layout ပြန်တွက်ရတဲ့ ကောင်တွေ တတ်နိုင်သလောက် ရှောင်ပြီး composition phase only property တွေသုံးလိုက်ရင် performance တော်တော်တက်လာမှာပါ။

--

--