淺談瀏覽器加載原理

 

       要理解瀏覽器的工做原理首先要對瀏覽器有一個初步的認識(幾個主流的瀏覽器:IE、Chrome、Firefox、afari、Opera),瀏覽器中最核心的部分是渲染引擎(Rendering Engine),也就是所謂的「瀏覽器內核」css

  其實瀏覽器的內核除渲染引擎外還包括JS引擎,前者決定了瀏覽器如何顯示網頁的內容以及頁面的格式信息,主要負責對網頁愈發的解釋並渲染;後者則是對JavaScript進行解釋、編譯和執行,從而使網頁達到一些動態效果html

  最開始的時候兩者並無很明確的區分,只不過隨着JS引擎愈來愈獨立,後來提起內核咱們就更傾向於指的是渲染引擎瀏覽器

瀏覽器的工做流程

  當咱們在瀏覽器地址欄中敲如url回車後瀏覽器工做流程大體是這樣的:瀏覽器開啓網絡請求線程,向服務器發送完整的http請求,再由服務器把數據返回到瀏覽器中,期間經歷了一系列流程如:DNS查詢、TCP/IP請求構建、五層因特網網絡協議等緩存

  瀏覽器在接收到內容後首先會根據文件的編碼格式如UTF-8將字節流轉爲字符流,而後語法解析器根據標籤的開始、標籤的結束、屬性等將html解析成Token(好比<p class='test' >helloworld</p> 就能夠拆分爲<p標籤的開始、class='test'屬性、</p>標籤的結束)接下來就會把這些詞構成一顆DOM樹性能優化

  瀏覽器也會將CSS樣式解析成CSSOM樹,以後會根據樣式的Selector將CSSOM和DOM合併成爲Render Tree,最後瀏覽器會根據Render Tree 計算佈局與元素的大小並繪製整個頁面。服務器

瀏覽器是多進程的

  瀏覽器是多進程的,有一個主控進程,以及每個tab頁面都會新開一個進程(某些狀況下多個tab會合並進程)網絡

進程可能包括主控進程,插件進程,GPU,tab頁(瀏覽器內核)等。多線程

  • Browser進程:瀏覽器的主進程(負責協調、主控),只有一個
  • 第三方插件進程:每種類型的插件對應一個進程,僅當使用該插件時才建立
  • GPU進程:最多一個,用於3D繪製
  • 瀏覽器渲染進程(內核):默認每一個Tab頁面一個進程,互不影響,控制頁面渲染,腳本執行,事件處理等(有時候會優化,如多個空白tab會合併成一個進程

瀏覽器渲染引擎是多線程的

    • js引擎線程
      • JS引擎一直等待着任務隊列中任務的到來,而後加以處理,一個Tab頁(renderer進程)中不管何時都只有一個JS線程在運行JS程序
    • GPU渲染線程
      • 注意,GUI渲染線程與JS引擎線程是互斥的,當JS引擎執行時GUI線程會被掛起(至關於被凍結了),GUI更新會被保存在一個隊列中等到JS引擎空閒時當即被執行。
    • 定時器線程
      • 傳說中的setInterval與setTimeout所在線程
      • 瀏覽器定時計數器並非由JavaScript引擎計數的,(由於JavaScript引擎是單線程的, 若是處於阻塞線程狀態就會影響記計時的準確)
      • 所以經過單獨線程來計時並觸發定時(計時完畢後,添加到事件隊列中,等待JS引擎空閒後執行)
      • 注意,W3C在HTML標準中規定,規定要求setTimeout中低於4ms的時間間隔算爲4ms。
    • 事件觸發線程
    • 異步http請求線程
      • 在XMLHttpRequest在鏈接後是經過瀏覽器新開一個線程請求
      • 將檢測到狀態變動時,若是設置有回調函數,異步線程就產生狀態變動事件,將這個回調再放入事件隊列中。再由JavaScript引擎執行。

迴流與重繪

【迴流】

  迴流是指窗口尺寸被修改、發生滾動操做,或者元素位置相關屬性被更新時會觸發佈局過程,在佈局過程當中要計算全部元素的位置信息。因爲HTML使用的是流式佈局,若是頁面中的一個元素的尺寸發生了變化,則其後續的元素位置都要跟着發生變化,也就是從新進行流式佈局的過程,因此被稱之爲迴流異步

觸發迴流包括以下操做:函數

  一、DOM元素的幾何屬性變化

  二、DOM樹的結構變化

       三、改變元素的一些樣式

  四、調整瀏覽器窗口大小

  五、獲取下列屬性

offsetTop\offsetLeft\offsetWidth\offsetHeight\scrollTop\scrollLeft\scrollWidth\scrollHeight\clientTop\clientLeft\clientWidth\clientHeight\getComputedStyle()\currentStyle()

 

  觸發迴流必定會觸發後續的重繪操做,並且對一個元素的迴流,可能會影響到父級元素。好比子元素浮動後,父元素會出現高度塌陷的狀況。因此,性能優化的重點在於儘可能只觸發小規模的重繪,儘可能不觸發迴流

【重繪】

  重繪是指當與視覺相關的樣式屬性值被更新時會觸發繪製過程,在繪製過程當中要從新計算元素的視覺信息,使元素呈現新的外觀因爲元素的重繪repaint只發生在渲染層 render layer上。因此,若是要改變元素的視覺屬性,最好讓該元素成爲一個獨立的渲染層render layer

  下面以元素顯示爲例,進行說明。實現元素顯示隱藏的方式有不少

  display: none/block,會引發迴流,從而引發重繪,性能較差

  visibility: visibile/hidden,只引發重繪,但因爲沒有成爲一個獨立的渲染層,會引發整個頁面(或當前渲染層)的重繪,性能較好

  opacity: 0/1,opacity小於1時,會產生render layer。因此opacity在0、1的變化中,引發了render layer的生成和銷燬,所以,也會引發迴流,從而引發重繪,性能較差。若是opacity: 0/0.9,則只會引發重繪

  若是對一個元素使用硬件加速渲染,如具備CSS 3D屬性,則不會進行重繪和迴流。但若是使用硬件渲染的元素過多,會形成GPU的傳輸壓力

【性能優化】

  下面列舉一些減小回流次數的方法

  一、不要一條一條地修改DOM樣式,而是修改className或者修改style.cssText

  二、在內存中屢次操做節點,完成後再添加到文檔中去

  三、對於一個元素進行復雜的操做時,能夠先隱藏它,操做完成後再顯示

  四、在須要常常獲取那些引發瀏覽器迴流的屬性值時,要緩存到變量中

  五、不要使用table佈局,由於一個小改動可能會形成整個table從新佈局。並且table渲染一般要3倍於同等元素時間

  此外,將須要屢次重繪的元素獨立爲render layer渲染層,如設置absolute,能夠減小重繪範圍;對於一些進行動畫的元素,能夠進行硬件渲染,從而避免重繪和迴流

【參考】:

https://www.cnblogs.com/xiaohuochai/p/9174471.html

https://www.jianshu.com/p/1e455a9226ce

相關文章
相關標籤/搜索