摘要:前端渲染過程的二三事本文不會介紹整個前端渲染過程的步驟,只是記錄最近閱讀的文章的些許思考和感悟。那么現(xiàn)在我們可以明白這個問題的關鍵所在了,因為在大部分頁面中是擁有的,而由于其解析順序,那么在事件之前必定已經(jīng)成功構造樹。
前端渲染過程的二三事
本文不會介紹整個前端渲染過程的步驟,只是記錄最近閱讀的文章的些許思考和感悟。(文章地址一(系列),文章地址二)
希望大家在閱讀這篇文章之前能將上述文章仔細瀏覽一篇,因為本文所述基本是基于其內(nèi)容。
Navigation Timing API和瀏覽器加載事件Navigation Timing API:可通過打?。╬erformance)查看;
瀏覽器加載事件:domContentLoaded,onload
上圖整理了Navigation Timing API中的一些事件和瀏覽器加載事件的發(fā)生順序。
這些事件的含義是什么呢?我們直接引用文章地址一(系列)的介紹:
domLoading:這是整個過程的起始時間戳,瀏覽器即將開始解析第一批收到的 HTML 文檔字節(jié)。
domInteractive:表示瀏覽器完成對所有 HTML 的解析并且 DOM 構建完成的時間點。
domContentLoaded:表示 DOM 準備就緒并且沒有樣式表阻止 JavaScript 執(zhí)行的時間點,這意味著現(xiàn)在我們可以構建渲染樹了。
許多 JavaScript 框架都會等待此事件發(fā)生后,才開始執(zhí)行它們自己的邏輯。因此,瀏覽器會捕獲 EventStart 和 EventEnd 時間戳,讓我們能夠追蹤執(zhí)行所花費的時間。
domComplete:顧名思義,所有處理完成,并且網(wǎng)頁上的所有資源(圖像等)都已下載完畢,也就是說,加載轉環(huán)已停止旋轉。
loadEvent:作為每個網(wǎng)頁加載的最后一步,瀏覽器會觸發(fā) onload 事件,以便觸發(fā)額外的應用邏輯。
看了上述事件的介紹,大致了解了每個事件所代表的含義,但也帶著少許疑惑:
HTML解析是分批進行的嗎?為什么要分批進行?
domContentLoaded事件結束后可以構建渲染樹了,是否意味著CSSOM樹構建也在該事件之前就已完成?
domContentLoaded事件表示DOM準備就緒并且沒有樣式表阻止 JavaScript執(zhí)行的時間點,可是JavaScript執(zhí)行是在構建DOM樹之前,那這是不是意味著該事件在DOM樹構建完成后就執(zhí)行了?若是這與domInteractive事件有什么區(qū)別呢?
首先看第一個問題,我們直接用chrome控制臺的performance來看效果。
上圖中,上方的Network的藍條是HTML的下載時間,下方箭頭所指是HTML的解析時間。
從中我們可以得出HTML解析的確是分批進行,并且解析并不需要等HTML完全下載完。那為什么要分批進行呢?這個問題我找了許多資料也沒有得出結論,于是自己從中思考。假設不是分批進行,那實現(xiàn)會有兩種情況:1.等HTML全部下載完,再一起解析;2.每下載一定量的HTML就將其放入解析器等待排隊解析。前者首先肯定被排除,若HTML很大,會影響首屏加載速度,后者按理速度更快,或許其實現(xiàn)的難度以及可能會帶來的一些問題而沒有采用?這個問題思考了良久,感覺從理論上是可行的,但從技術角度,由于自己這方面的知識實在薄弱,所以也無法得知其實現(xiàn)的過程是否存在技術瓶頸。
第二個問題:CSSOM樹構建是否在domContentLoaded事件之前?
話不多說我們自己實踐。
首先我先創(chuàng)建一個HTML文件并寫入少許標簽,再創(chuàng)建一個CSS并于HTML引入,在CSS文件中寫入大量內(nèi)容(自己實踐時寫了5W多行)。然后用performance查看。
上圖每個箭頭代表的含義:
HTML解析結束時間
domContentLoaded加載時間
CSS文件下載完的時間
CSS文件解析的時間
從這個步驟以及其所處時間,我們可以清晰的得出,該結論不準確。那么該作者為什么會得出該結論呢,是他犯錯了嗎?我隨后發(fā)現(xiàn)他在這篇文章下面還寫了一句“domContentLoaded一般表示DOM和CSSOM均準備就緒的時間點”。那么這句話意味著大部分的時候CSSOM樹的構建是在domContentLoaded事件之前??墒沁@個大部分又指的是什么情況,這又涉及到另一個知識點“DOM樹,CSSOM樹,JS的三角關系”,構造DOM樹時遇見JS會先解析執(zhí)行JS,而在解析執(zhí)行JS時遇到CSSOM,又會先構造CSSOM樹,這個過程稍后會具體說明。那么現(xiàn)在我們可以明白這個問題的關鍵所在了,因為在大部分頁面中是擁有JS的,而由于其解析順序,那么在domContentLoaded事件之前必定已經(jīng)成功構造CSSOM樹。
第三個問題:domInteractive與domContentLoaded的區(qū)別是什么呢?這兩個事件中間是否還會進行其他操作?
我們都知道script標簽有defer和async兩個屬性。有了這兩個屬性,瀏覽器就會加一個進程下載JS。那么下載完的執(zhí)行時間點是在什么時候?其中async會在JS下載完后立馬執(zhí)行,也正是這個原因,會導致JS的執(zhí)行順序不一定按標簽的從上至下,而是按照下載完的時間。那么defer屬性的執(zhí)行時間呢,我想大家應該都能猜到了,它的執(zhí)行時間點的確就是在上述的兩個事件之間,那么我們也就得知這兩個事件的區(qū)別所在。
三大樹我們都知道前端渲染有三大樹:DOM樹,CSSOM樹,RENDER樹。那么這三大樹的構造時間和上述的事件執(zhí)行時間的順序又是怎樣的呢。
其中DOM樹和RENDER樹所在位置其實是顯而易見的,并且在之前內(nèi)容也已經(jīng)指出。DOM樹在domInteractive事件之前,RENDER樹在domContentLoaded事件之后。但是CSSOM樹就難以捉摸,其與DOM樹的關系,完全受到是否擁有JS影響。
在確定CSSOM樹所處位置前,我們先確定一個上面提到的概念:構造DOM樹時遇見JS會先解析執(zhí)行JS,而在解析執(zhí)行JS時遇到CSSOM,又會先構造CSSOM樹。官方給出的原因是,JS會使用document.write而改變DOM樹,所以構造DOM樹時碰到JS會先執(zhí)行JS;而JS在執(zhí)行時,需要查找CSS,所以執(zhí)行JS時,碰到構造CSSOM樹,會先構造CSSOM樹。但是這里有一點奇怪的時,JS也可以通過創(chuàng)造Link標簽的方式改變CSSOM樹,所以個人感覺官方的這種解釋有點牽強。不過官方的解釋雖然不能讓人完全信服,但這執(zhí)行順序是不會有錯的。
接下來我們分別通過有無JS兩大類確認CSSOM樹所處位置:
無JS的情況
由于DOM樹和CSSOM樹是并行解析的情況,所以這兩個樹構建完成的順序完全無法固定,只由它們自己本身大小有關。因此CSSOM樹構建完成的時間既可能在domInteractive之前,可能在domContentLoaded之后,也可能在這兩事件之間。
有JS的情況
這里我們先假設CSS文件很小,在沒還解析到JS時就已完成解析,那么這種情況其實必定發(fā)生在domInteractive之前,因為都還沒解析到JS,說明DOM樹必定沒有構建完成。那么再假設CSS文件很大,然后中途遇到JS文件,這時候JS文件發(fā)現(xiàn)在構造CSSOM樹,其就會等待CSSOM樹構建完成后再解析執(zhí)行JS,所以這種情況CSSOM也必定在domInteractive之前。
但是有2個有意思的情況:
(1) 如果我們動態(tài)創(chuàng)建link標簽并添加到html中,那么又會發(fā)生什么呢?若JS還沒解析執(zhí)行完,那么會停止JS而去解析CSS,若JS已執(zhí)行完那么CSSOM樹其實也不是必定在domInteractive之前。(當然這可能已經(jīng)不算初次渲染構建)
(2) link標簽放到JS后面又會發(fā)生什么呢?這種情況我發(fā)現(xiàn)不管我怎么嘗試,CSSOM樹必定在DOM樹構建之前構建,但其又在JS執(zhí)行完成后。如果有興趣的同學可以查查是為什么。
其實前端渲染是一個很龐大的知識點,并且其涉及的周邊知識也及其龐大,本文只是對其中一個小知識點做了思考和實踐。最后要說的一點是,以上內(nèi)容,純屬個人見解,如有不當,請多指教。
文章版權歸作者所有,未經(jīng)允許請勿轉載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉載請注明本文地址:http://systransis.cn/yun/99186.html
摘要:常用的數(shù)組方法刪除數(shù)組的最后一個元素,返回被刪除的元素,原數(shù)組長度減。原數(shù)組發(fā)生了變化,但沒有創(chuàng)建新的數(shù)組。將指定數(shù)組進行排序,返回排好序的數(shù)組。顛倒數(shù)組元素的順序,返回逆序后的數(shù)組。 數(shù)組,對于每一個前端人員來說是非常常見且重要的數(shù)據(jù)結構之一,也是面試常常出現(xiàn)的題目,掌握數(shù)組的方法能幫助我們更高效地處理問題。不過在數(shù)組的學習中,我們常常會混淆數(shù)組本身的方法和Javascript提供的...
摘要:傳統(tǒng)的網(wǎng)頁編程采用的三劍客來實現(xiàn),在微信小程序中同樣有三劍客。觀察者模式不難實現(xiàn),重點是如何在微信小程序中搭配其特有的生命周期來使用。交互事件傳統(tǒng)的事件傳遞類型有冒泡型與捕獲型,微信小程序中自然也有。 本文由作者鄒永勝授權網(wǎng)易云社區(qū)發(fā)布。 簡介為了更好的展示我們即時通訊SDK強悍的能力,網(wǎng)易云信IM SDK微信小程序DEMO的開發(fā)就提上了日程。用產(chǎn)品的話說就是: 云信 IM 小程序 S...
摘要:但對于整個事件流上的別的元素來說,執(zhí)行順序還會受到另外一個因素的影響。以上面的場景為例,在捕獲階段執(zhí)行的事件,如果執(zhí)行,則事件流終止,不會到達目標階段,的世界則不會被執(zhí)行執(zhí)行結果為線上參考事件流 向dom綁定事件的事件的三種方式 行內(nèi)綁定 按鈕 js內(nèi)綁定 btnDom.onclick = function clickHandler() { console.log(click)...
摘要:分表字段的選擇。問題產(chǎn)生之前提到在分表應用上線前我們需要將原有表的數(shù)據(jù)遷移到新表中,這樣才能保證業(yè)務不受影響。雖說凌晨的業(yè)務量下降,但依然有少部分的請求過來,也會出現(xiàn)各種數(shù)據(jù)庫異常。 showImg(https://segmentfault.com/img/remote/1460000019462791?w=496&h=285); 前言 本篇是上一篇《一次分表踩坑實踐的探討》,所以還沒...
閱讀 3202·2023-04-26 01:39
閱讀 3354·2023-04-25 18:09
閱讀 1623·2021-10-08 10:05
閱讀 3241·2021-09-22 15:45
閱讀 2790·2019-08-30 15:55
閱讀 2401·2019-08-30 15:54
閱讀 3173·2019-08-30 15:53
閱讀 1335·2019-08-29 12:32