摘要:例如,當(dāng)解析器被腳本阻塞時(shí),解析器雖然會(huì)停止構(gòu)建,但仍會(huì)識(shí)別該腳本后面的資源,并進(jìn)行預(yù)加載。也就是說(shuō),會(huì)阻塞頁(yè)面的渲染但是,并不會(huì)阻塞的解析。的加載不會(huì)阻塞頁(yè)面的渲染和資源的加載,一旦加載到就會(huì)立刻執(zhí)行。
大家是不是會(huì)遇到這樣的一個(gè)問(wèn)題,頁(yè)面加載速度過(guò)慢,瀏覽器老在轉(zhuǎn)圈圈,頁(yè)面部分內(nèi)容需要花費(fèi)較多的時(shí)間才能加載出來(lái)?
要明白上述問(wèn)題,我們需要知道是什么在阻塞頁(yè)面的渲染?
1、瀏覽器如何渲染?1.1、渲染引擎介紹
要先說(shuō)明:Firebox 的渲染引擎是 Geoko,chrome的渲染引擎是wekit。本文使用的是chrome瀏覽器
1.2、渲染的主要過(guò)程
簡(jiǎn)單介紹
瀏覽器解析 DOM 生成 DOM Tree, 結(jié)合CSS 生成的 CSS Tree, 最終組成 Render Tree,再渲染頁(yè)面。因此 在此過(guò)程 css 不會(huì)阻塞 DOM 解析。
詳細(xì)介紹
流程示意圖
幾個(gè)概念:
DOM Tree:瀏覽器將HTML解析成樹(shù)形的數(shù)據(jù)結(jié)構(gòu)
CSS Rule Tree:瀏覽器將 CSS 解析成樹(shù)形的數(shù)據(jù)結(jié)構(gòu)
Render Tree:DOM 和 CSSOM 合并后生成 Render Tree
layout:有了Render Tree, 瀏覽器已經(jīng)知道網(wǎng)頁(yè)中有哪些節(jié)點(diǎn)、各個(gè)節(jié)點(diǎn)的CSS定義以及他們的從屬關(guān)系,從而去計(jì)算出每個(gè)節(jié)點(diǎn)在屏幕中的位置
painting:按照算出來(lái)的規(guī)則,把內(nèi)容畫(huà)到屏幕上
reflow(回流):當(dāng)瀏覽器發(fā)現(xiàn)某個(gè)部分發(fā)生了點(diǎn)變化影響了布局,需要倒回去重新渲染,這個(gè)過(guò)程稱(chēng)為 reflow。reflow 會(huì)從 這個(gè) root frame 開(kāi)始遞歸往下,依次計(jì)算所有的結(jié)點(diǎn)尺寸和位置。reflow 是無(wú)法避免的。目前界面上流行的一些效果,比如樹(shù)狀目錄的折疊、展開(kāi)(實(shí)質(zhì)上是元素的顯示與隱藏)等,都將引起瀏覽器的 reflow。鼠標(biāo)滑過(guò)、點(diǎn)擊等等... 只要這些行為引起了頁(yè)面上某些元素的占位面積、定位方式、邊距等屬性的變化,都會(huì)引起它內(nèi)部、周?chē)踔琳麄€(gè)頁(yè)面的重新渲染
repaint(重繪):改變某個(gè)元素的背景色、文字顏色、邊框顏色等等不影響它周?chē)騼?nèi)部布局的屬性時(shí),屏幕的一部分要重畫(huà),但是元素的幾何尺寸沒(méi)有變。
注意:
(1)display:none 的節(jié)點(diǎn)不會(huì)被加入Render Tree, 而 visibility:hidden則會(huì);所以,如果某個(gè)節(jié)點(diǎn)最開(kāi)始是不顯示的,設(shè)為display:none 是更優(yōu)的。
(2)display:none 會(huì)觸發(fā)reflow, 而 visibility:hidden 只會(huì)觸發(fā)repaint,因?yàn)槲恢脹](méi)有變化
(3)有些情況下,比如修改了元素的樣式瀏覽器并不會(huì)立刻reflow 或 repaint 一次,而是會(huì)把這樣的操作積攢一批,然后做一次 reflow,這叫 異步 reflow 或 增量異步 reflow。但是在有些情況下,比如resize 窗口,改變了頁(yè)面默認(rèn)的字體等。對(duì)于這些操作,瀏覽器會(huì)馬上進(jìn)行reflow。
webkit 的主要流程:
Geoko 的主要流程:
完整流程解析:
(1)瀏覽器將 HTML 解析成DOM 樹(shù),當(dāng)前節(jié)點(diǎn)的所有子節(jié)點(diǎn)都構(gòu)建好后才會(huì)去構(gòu)建當(dāng)前節(jié)點(diǎn)的下一個(gè)兄弟節(jié)點(diǎn)。
(2)將CSS 解析成 CSS Rule Tree
(3)根據(jù)DOM 樹(shù) 和 CSSOM 構(gòu)造 Render Tree。注意,display:none 不會(huì)被掛載到 Render Tree 上面
(4)計(jì)算出每個(gè)節(jié)點(diǎn)在屏幕中的位置
(5)繪制!
注意:渲染引擎將會(huì)盡可能早的將內(nèi)容呈現(xiàn)到屏幕上,并不會(huì)等到所有的html都解析完成之后再去構(gòu)建和布局render tree。它是解析完一部分內(nèi)容就顯示一部分內(nèi)容,同時(shí),可能還在通過(guò)網(wǎng)絡(luò)下載其余內(nèi)容
展示一下。display:none 與 visibility:hidden 在瀏覽器上的區(qū)別
display:none
visibility:hidden
2、阻塞渲染:CSS 與 javascript討論資源的阻塞時(shí),我們要清楚,現(xiàn)代瀏覽器總是并行加載資源。例如,當(dāng)HTML解析器(HTML Parser) 被腳本阻塞時(shí),解析器雖然會(huì)停止構(gòu)建DOM,但仍會(huì)識(shí)別該腳本后面的資源,并進(jìn)行預(yù)加載。
同時(shí),由于下面兩點(diǎn):
默認(rèn)情況下,CSS 被視為阻塞渲染的資源,這意味著瀏覽器不會(huì)渲染任何已處理的內(nèi)容,直至CSSOM構(gòu)建完畢
javascript 不僅可以讀取和修改DOM 屬性,還可以讀取和修改CSSOM 屬性
存在阻塞的 CSS 資源時(shí), 瀏覽器會(huì)延遲javascript 的執(zhí)行和 Render Tree 構(gòu)建。
另外
當(dāng)瀏覽器遇到一個(gè)script標(biāo)記時(shí),DOM 構(gòu)建將暫停,直至腳本完成執(zhí)行。
javascript 可以查詢和修改 DOM 與 CSSOM
CSSOM 構(gòu)建時(shí),javascript 執(zhí)行將暫停,直至 CSSOM 就緒。
所以,script 標(biāo)簽的位置很重要。實(shí)際使用時(shí),可以遵循下面2個(gè)原則
CSS 優(yōu)先:引入順序上,CSS 資源優(yōu)于javascript資源
javascript 應(yīng)盡量少影響 DOM 的構(gòu)建
2.1、CSS 會(huì)阻塞渲染嗎?從瀏覽器的渲染原理來(lái)看,渲染引擎會(huì)將css 構(gòu)建成 CSSOM Tree 然后再渲染頁(yè)面。也就是說(shuō),CSS 會(huì) 阻塞 頁(yè)面的渲染!但是,CSS 并不會(huì)阻塞 DOM 的解析。(因?yàn)樾枰哂?DOM 以及 CSSOM 才會(huì)構(gòu)建渲染樹(shù))
2.2、JS 會(huì)阻塞渲染嗎?看以下代碼:
dsaffffdadas
下面這段代碼會(huì)在瀏覽器上面顯示一個(gè)綠色的盒子
第2個(gè)例子,在頭部引入JS
// new_file.js let arr = [] for (let i = 0; i < 10000000; i++) { arr.push(i); arr.splice(i%3, i%7 ,i %5); } let div= document.querySelector("div"); console.log(div);
box1box3
瀏覽器會(huì)先轉(zhuǎn)圈圈,最后在顯示 盒子
也就是說(shuō),為什么大部分程序都會(huì)將 js 放在 底部,css 放在頂部 就是為了加速頁(yè)面的渲染
3、我們?nèi)绾胃淖冏枞F(xiàn)狀?defer 與 async3.1、defer 與 async 的介紹
defer:js的加載不會(huì)阻塞頁(yè)面的渲染和資源的加載,defer 會(huì)按照原本js的順序執(zhí)行。
async:js 的加載不會(huì)阻塞頁(yè)面的渲染和資源的加載,一旦加載到就會(huì)立刻執(zhí)行。如果js前后有依賴性,最好不要用async。
3.2、defer 與 async的區(qū)別
3.2.1、相同點(diǎn):
加載文件時(shí)不阻塞頁(yè)面渲染
box1box3
// new_file.js let arr = [] for (let i = 0; i < 10000000; i++) { arr.push(i); arr.splice(i%3, i%7 ,i %5); } let div= document.querySelector("div"); console.log(div);
會(huì)在一運(yùn)行的時(shí)候,就在頁(yè)面中顯示2個(gè)盒子,因此不阻塞
對(duì)于inline的script(內(nèi)聯(lián)腳本)無(wú)效
瀏覽器按順序打印!
使用這兩個(gè)屬性的腳本中不能調(diào)用document.write 方法
// new_file.js let arr = [] for (let i = 0; i < 10000000; i++) { arr.push(i); arr.splice(i%3, i%7 ,i %5); } let div= document.querySelector("div"); console.log(div); document.write("asdadasas");
有腳本的onload 事件回調(diào)
3.2.2、不同點(diǎn):
每一個(gè)async 屬性的腳本都在它下載結(jié)束后之后立刻執(zhí)行,同時(shí)會(huì)在window的load事件之前執(zhí)行。
每一個(gè)defer屬性的腳本都是在頁(yè)面解析完畢之后,按照原本的屬性執(zhí)行,同時(shí)會(huì)在document的DOMContentLoader之前執(zhí)行
參(抄)考(襲)文章:
https://juejin.im/post/59c606... 原來(lái) CSS 與 JS 是這樣阻塞 DOM 解析和渲染的
https://juejin.im/entry/59e1d... 瀏覽器的渲染:過(guò)程與原理
https://juejin.im/post/5a1229... script中defer和async的區(qū)別
https://www.cnblogs.com/Bonni... load/domContentLoaded事件、異步/延遲Js 與DOM解析
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/100293.html
摘要:加載會(huì)阻塞運(yùn)行嗎由上面的推論,我們可以得出,加載不會(huì)阻塞樹(shù)解析,但是會(huì)阻塞樹(shù)渲染。這也就說(shuō)明了,加載會(huì)阻塞后面的語(yǔ)句的執(zhí)行。因此,加載是會(huì)阻塞的渲染的。 之前面試今日頭條的時(shí)候,今日頭條面試官問(wèn)我,js執(zhí)行會(huì)阻塞DOM樹(shù)的解析和渲染,那么css加載會(huì)阻塞DOM樹(shù)的解析和渲染嗎?所以,接下來(lái)我就來(lái)對(duì)css加載對(duì)DOM樹(shù)的解析和渲染做一個(gè)測(cè)試。 為了完成本次測(cè)試,先來(lái)科普一下,如何利用ch...
摘要:加載會(huì)阻塞運(yùn)行嗎由上面的推論,我們可以得出,加載不會(huì)阻塞樹(shù)解析,但是會(huì)阻塞樹(shù)渲染。這也就說(shuō)明了,加載會(huì)阻塞后面的語(yǔ)句的執(zhí)行。因此,加載是會(huì)阻塞的渲染的。 之前面試今日頭條的時(shí)候,今日頭條面試官問(wèn)我,js執(zhí)行會(huì)阻塞DOM樹(shù)的解析和渲染,那么css加載會(huì)阻塞DOM樹(shù)的解析和渲染嗎?所以,接下來(lái)我就來(lái)對(duì)css加載對(duì)DOM樹(shù)的解析和渲染做一個(gè)測(cè)試。 為了完成本次測(cè)試,先來(lái)科普一下,如何利用ch...
摘要:加載會(huì)阻塞運(yùn)行嗎由上面的推論,我們可以得出,加載不會(huì)阻塞樹(shù)解析,但是會(huì)阻塞樹(shù)渲染。這也就說(shuō)明了,加載會(huì)阻塞后面的語(yǔ)句的執(zhí)行。因此,加載是會(huì)阻塞的渲染的。 之前面試今日頭條的時(shí)候,今日頭條面試官問(wèn)我,js執(zhí)行會(huì)阻塞DOM樹(shù)的解析和渲染,那么css加載會(huì)阻塞DOM樹(shù)的解析和渲染嗎?所以,接下來(lái)我就來(lái)對(duì)css加載對(duì)DOM樹(shù)的解析和渲染做一個(gè)測(cè)試。 為了完成本次測(cè)試,先來(lái)科普一下,如何利用ch...
摘要:加載會(huì)阻塞運(yùn)行嗎由上面的推論,我們可以得出,加載不會(huì)阻塞樹(shù)解析,但是會(huì)阻塞樹(shù)渲染。這也就說(shuō)明了,加載會(huì)阻塞后面的語(yǔ)句的執(zhí)行。從流程我們可以看出來(lái)解析和解析是兩個(gè)并行的進(jìn)程,所以這也解釋了為什么加載不會(huì)阻塞的解析。因此,加載是會(huì)阻塞的渲染的。 本文由云+社區(qū)發(fā)表作者:嘿嘿嘿 可能大家都知道,js執(zhí)行會(huì)阻塞DOM樹(shù)的解析和渲染,那么css加載會(huì)阻塞DOM樹(shù)的解析和渲染嗎?接下來(lái),我就來(lái)對(duì)...
摘要:加載會(huì)阻塞運(yùn)行嗎由上面的推論,我們可以得出,加載不會(huì)阻塞樹(shù)解析,但是會(huì)阻塞樹(shù)渲染。這也就說(shuō)明了,加載會(huì)阻塞后面的語(yǔ)句的執(zhí)行。從流程我們可以看出來(lái)解析和解析是兩個(gè)并行的進(jìn)程,所以這也解釋了為什么加載不會(huì)阻塞的解析。因此,加載是會(huì)阻塞的渲染的。 本文由云+社區(qū)發(fā)表作者:嘿嘿嘿 可能大家都知道,js執(zhí)行會(huì)阻塞DOM樹(shù)的解析和渲染,那么css加載會(huì)阻塞DOM樹(shù)的解析和渲染嗎?接下來(lái),我就來(lái)對(duì)...
摘要:加載會(huì)阻塞運(yùn)行嗎由上面的推論,我們可以得出,加載不會(huì)阻塞樹(shù)解析,但是會(huì)阻塞樹(shù)渲染。這也就說(shuō)明了,加載會(huì)阻塞后面的語(yǔ)句的執(zhí)行。從流程我們可以看出來(lái)解析和解析是兩個(gè)并行的進(jìn)程,所以這也解釋了為什么加載不會(huì)阻塞的解析。因此,加載是會(huì)阻塞的渲染的。 本文由云+社區(qū)發(fā)表作者:嘿嘿嘿 可能大家都知道,js執(zhí)行會(huì)阻塞DOM樹(shù)的解析和渲染,那么css加載會(huì)阻塞DOM樹(shù)的解析和渲染嗎?接下來(lái),我就來(lái)對(duì)...
閱讀 1814·2021-10-09 09:44
閱讀 2690·2021-09-22 15:38
閱讀 2451·2021-09-09 09:33
閱讀 686·2021-09-07 09:58
閱讀 1785·2021-09-02 15:41
閱讀 2485·2019-08-30 15:55
閱讀 1796·2019-08-30 15:55
閱讀 533·2019-08-30 15:44