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