瀏覽器渲染頁面的過程以及原理

什么是瀏覽器渲染

簡單來說,就是將HTML字符串 —> 像素信息

在這里插入圖片描述

在這里插入圖片描述

渲染時間點

瀏覽器什么時候開始渲染?

  1. 網絡線程發送請求,取回HTML封裝為渲染任務并將其傳遞給渲染主線程的消息隊列。

    問題:只取回HTML嗎?那CSS和JS呢?

    其實這兩者都在HTML中,分別以link和script引入。

  2. 在事件循環機制的作用下,「渲染主線程」從消息隊列中取出任務,開始渲染頁面

在這里插入圖片描述

渲染主線程一步一步處理,最終渲染好整個頁面

在這里插入圖片描述

整個渲染流程分為多個階段,分別是: HTML 解析、樣式計算、布局、分層、繪制、分塊、光柵化、畫。

每個階段都有明確的輸入輸出,上一個階段的輸出會成為下一個階段的輸入。

這樣,整個渲染流程就形成了一套組織嚴密的生產流水線。

下面詳細講述一下每一步都進行了哪些操作。

渲染頁面的詳細步驟

1.解析HTML

渲染主線程拿到網絡進程下載好的HTML字符串,將其解析為DOM樹和CSSOM樹。

這兩個樹是C++對象(因為瀏覽器是用C++寫的),不過在C++對象外部套了一層JS,所以我們可以通過JS操作這兩個樹。

為什么要處理成「樹」對象?

因為直接操作HTML字符串太過于復雜,將其變為對象后,直觀且便于操作。

在這里插入圖片描述

什么是DOM樹

DOM樹的根節點是document,也就是我們平時寫的元素結構。

它本身是一個對象,可以通過console.dir(document)查看

在這里插入圖片描述

在這里插入圖片描述

處理為對象后,更加便于操作。

在這里插入圖片描述

什么是CSSOM樹

和DOM樹類似,不過它是CSS對象,根節點叫做StyleSheetList,它是各種樣式表的集合,比如內部樣式表,外部樣式表,內聯(行內)樣式表, 瀏覽器默認樣式表。多個表對應多個CSStyleSheet。

在這里插入圖片描述

瀏覽器默認樣式表是什么?

控制臺中,帶有user agent stylesheet標識的就是瀏覽器默認樣式表。

在這里插入圖片描述

怎么查看全部的瀏覽器默認樣式表?

可以通過github查看Chrome的源碼,這里推薦一個小插件,幫助我們不用下載就可以在vscode快速查看Chrome源碼,這個插件叫做GitHub Repositories。

在這里插入圖片描述

下載完畢后,可以直接通過url查看Chrome源代碼。

在這里插入圖片描述

點擊這個圖標登錄綁定github賬號后,直接通過url打開并查看代碼。

在這里插入圖片描述

打開后,我們可以根據路徑查看瀏覽器默認樣式表。

third_party > blink > renderer > core > html > resources > html.css

在這里插入圖片描述

JS如何操作CSSOM樹?

常見的方法

dom元素.style
document.styleSheets  // 這個數組其實就是CSStyleSheetList

示例,將頁面中所有div添加一個紅色邊框

document.styleSheets[0].addRule('div','border:1px solid red !important')

在這里插入圖片描述

其實Vue框架的實現就用到了該方法。

解析過程中遇到CSS怎么辦

為了提高解析效率,瀏覽器會啟動一個預解析器率先下載和解析CSS。

預解析器瀏覽速度很快,他只負責找到CSS、JS并通知「網絡線程」,下載完畢后初步解析后交給「渲染主線程」繼續處理。

期間「渲染主線程」如果發現CSS,會直接跳過,繼續處理后面的HTML,直到「預解析線程」初步解析CSS完畢后,才會繼續處理。

在這里插入圖片描述

解析過程中遇到JS怎么辦

與CSS不同的是,「渲染主線程」遇到JS代碼時,必須暫停一切行為,等待下載完成后才繼續解析HTML。因為「渲染主線程」無法確定JS中是否改動了之前解析的dom。

在這里插入圖片描述

2.樣式計算

這一步將DOM結構和CSS合并,計算后得到每一個節點的最終樣式(計算后的樣式)。

在這里插入圖片描述

其實就是CSS屬性計算過程,例如層疊(權重)、繼承。比如類選擇器和id選擇器中的樣式,需要判斷層疊性。

這一步的過程中很多預設值會變成絕對值,比如顏色red會變成rgb(255,0,0),相對單位會變成絕對單位。

這一步完成后,會得到一棵帶有樣式的DOM樹。

3.布局

這一步「渲染主線程」會遍歷上一步的DOM樹,依次計算出每個節點的大小以及位置。計算完成后的樹叫做Layout樹。

在這里插入圖片描述

CSS中不是有寬高嗎,為什么還要計算?

因為有的情況元素沒有設置寬高,那么就是auto,會根據其內容計算。

每個節點的位置是根據什么計算的呢?

是根據他父元素嗎?

答案是否定的。其實是根據其「包含塊」元素的位置,比如一個元素是絕對定位,但其父元素并非相對定位,但父元素的父元素是相對定位,那么這個元素的包含塊就是他的爺爺元素。這個元素能根據他父元素計算位置嗎?必然不能,會根據它的爺爺元素。

DOM樹和Layout樹的節點不一定一一對應

有些display為none的元素不會被渲染。

在這里插入圖片描述

偽元素會新生成一個節點。

在這里插入圖片描述

內容必須在行盒中,行盒和塊盒不能相鄰。

在這里插入圖片描述

Layout樹中的每一個節點并不是dom對象,而是C++對象,JS是獲取不到的。但是可以獲取到一些信息,比如常用的document.body.clientWidth等都是從「布局樹」中獲取的。

4.分層

瀏覽器會自動分層,將來某一個層發生改變后,僅對該層進行修改,以確保修改后再次渲染時的高效。

堆疊上下文會影響分層,例如z-index、opacity、transform。

在這里插入圖片描述

如何查看圖層

  1. 添加圖層工具

    在這里插入圖片描述

  2. 展開發現,有很多圖層

    在這里插入圖片描述

代碼無法讓瀏覽器分層,但可以使用給元素添加css,瀏覽器可能會為其設置單獨圖層。

.container{will-change: transform
}

5.繪制

繪制后會為每個圖層生成繪制指令。

在這里插入圖片描述

「渲染主線程」至此,已經做完了全部操作,其余的步驟交給其他線程。

在這里插入圖片描述

6.分塊

完成繪制后,「渲染主線程」會將每個涂層的繪制信息提交給「合成線程」,「合成線程」將每一個圖層分成多個小區域。

它會從線程池中拿取多個線程來完成分塊工作。

在這里插入圖片描述

7.光柵化

將每個塊變成位圖,優先處理靠近視口的塊。

在這里插入圖片描述

此過程會用到GPU加速

在這里插入圖片描述

8.畫

合成線程拿到每個位圖在屏幕上的位置,交給GPU完成最終呈現。

在這里插入圖片描述

完整過程

在這里插入圖片描述

  1. 生成DOM樹和CSSOM樹
  2. 將DOM樹和CSSOM樹融合成新的DOM樹(結構樣式相結合)
  3. 將DOM樹處理為Layout樹(忽略display:none的元素)
  4. 將Layout樹分層(修改dom后只重新渲染其所在圖層)
  5. 繪制每個圖層,用于渲染
  6. 將繪制好的圖層分塊
  7. 將每個塊處理成位圖(GPU做的)
  8. GPU最終「畫」出頁面

常見面試題

什么是reflow

reflow 的本質就是重新計算 layout 樹。

當進行了會影響布局樹的操作后,需要重新計算布局樹,會引發 layout。

為了避免連續的多次操作導致布局樹反復計算,瀏覽器會合并這些操作,當 JS 代碼全部完成后再進行統一計算。所以,改動屬性造成的 reflow 是異步完成的。

也同樣因為如此,當 JS 獲取布局屬性時,就可能造成無法獲取到最新的布局信息。

瀏覽器在反復權衡下,最終決定獲取屬性立即 reflow。

常見操作如幾何尺寸發生改變,CSSOM發生改變,需要重新計算布局樹。

在這里插入圖片描述

什么是repaint

repaint 的本質就是重新根據分層信息計算了繪制指令。

當改動了可見樣式后,就需要重新計算,會引發 repaint。

由于元素的布局信息也屬于可見樣式,所以 reflow 一定會引起 repaint。

常見操作如顏色發生改變,會跳過計算布局和分層,會比reflow塊。

在這里插入圖片描述

為什么transform效率高

因為 transform 既不會影響布局也不會影響繪制指令,它影響的只是渲染流程的最后一個「draw」階段

由于 draw 階段在合成線程中,所以 transform 的變化幾乎不會影響渲染主線程。反之,渲染主線程無論如何忙碌,也不會影響 transform 的變化。

在這里插入圖片描述

在這里插入圖片描述

總結

當瀏覽器的網絡線程收到 HTML 文檔后,會產生一個渲染任務,并將其傳遞給渲染主線程的消息隊列。

在事件循環機制的作用下,渲染主線程取出消息隊列中的渲染任務,開啟渲染流程。


整個渲染流程分為多個階段,分別是: HTML 解析、樣式計算、布局、分層、繪制、分塊、光柵化、畫

每個階段都有明確的輸入輸出,上一個階段的輸出會成為下一個階段的輸入。

這樣,整個渲染流程就形成了一套組織嚴密的生產流水線。


渲染的第一步是解析 HTML

解析過程中遇到 CSS 解析 CSS,遇到 JS 執行 JS。為了提高解析效率,瀏覽器在開始解析前,會啟動一個預解析的線程,率先下載 HTML 中的外部 CSS 文件和 外部的 JS 文件。

如果主線程解析到link位置,此時外部的 CSS 文件還沒有下載解析好,主線程不會等待,繼續解析后續的 HTML。這是因為下載和解析 CSS 的工作是在預解析線程中進行的。這就是 CSS 不會阻塞 HTML 解析的根本原因。

如果主線程解析到script位置,會停止解析 HTML,轉而等待 JS 文件下載好,并將全局代碼解析執行完成后,才能繼續解析 HTML。這是因為 JS 代碼的執行過程可能會修改當前的 DOM 樹,所以 DOM 樹的生成必須暫停。這就是 JS 會阻塞 HTML 解析的根本原因。

第一步完成后,會得到 DOM 樹和 CSSOM 樹,瀏覽器的默認樣式、內部樣式、外部樣式、行內樣式均會包含在 CSSOM 樹中。


渲染的下一步是樣式計算

主線程會遍歷得到的 DOM 樹,依次為樹中的每個節點計算出它最終的樣式,稱之為 Computed Style。

在這一過程中,很多預設值會變成絕對值,比如red會變成rgb(255,0,0);相對單位會變成絕對單位,比如em會變成px

這一步完成后,會得到一棵帶有樣式的 DOM 樹。


接下來是布局,布局完成后會得到布局樹。

布局階段會依次遍歷 DOM 樹的每一個節點,計算每個節點的幾何信息。例如節點的寬高、相對包含塊的位置。

大部分時候,DOM 樹和布局樹并非一一對應。

比如display:none的節點沒有幾何信息,因此不會生成到布局樹;又比如使用了偽元素選擇器,雖然 DOM 樹中不存在這些偽元素節點,但它們擁有幾何信息,所以會生成到布局樹中。還有匿名行盒、匿名塊盒等等都會導致 DOM 樹和布局樹無法一一對應。


下一步是分層

主線程會使用一套復雜的策略對整個布局樹中進行分層。

分層的好處在于,將來某一個層改變后,僅會對該層進行后續處理,從而提升效率。

滾動條、堆疊上下文、transform、opacity 等樣式都會或多或少的影響分層結果,也可以通過will-change屬性更大程度的影響分層結果。


再下一步是繪制

主線程會為每個層單獨產生繪制指令集,用于描述這一層的內容該如何畫出來。


完成繪制后,主線程將每個圖層的繪制信息提交給合成線程,剩余工作將由合成線程完成。

合成線程首先對每個圖層進行分塊,將其劃分為更多的小區域。

它會從線程池中拿取多個線程來完成分塊工作。


分塊完成后,進入光柵化階段。

合成線程會將塊信息交給 GPU 進程,以極高的速度完成光柵化。

GPU 進程會開啟多個線程來完成光柵化,并且優先處理靠近視口區域的塊。

光柵化的結果,就是一塊一塊的位圖


最后一個階段就是

合成線程拿到每個層、每個塊的位圖后,生成一個個「指引(quad)」信息。

指引會標識出每個位圖應該畫到屏幕的哪個位置,以及會考慮到旋轉、縮放等變形。

變形發生在合成線程,與渲染主線程無關,這就是transform效率高的本質原因。

合成線程會把 quad 提交給 GPU 進程,由 GPU 進程產生系統調用,提交給 GPU 硬件,完成最終的屏幕成像。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/207071.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/207071.shtml
英文地址,請注明出處:http://en.pswp.cn/news/207071.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

面試經典150題(1-2)

leetcode 150道題 計劃花兩個月時候刷完,今天完成了兩道(1-2)150: (88. 合并兩個有序數組)題目描述: 給你兩個按 非遞減順序 排列的整數數組 nums1 和 nums2,另有兩個整數 m 和 n ,分別表示 n…

元宇宙vr黨建云上實景展館擴大黨的影響力

隨著科技的飛速發展,VR虛擬現實技術已經逐漸融入我們的日常生活,尤其在黨建領域,VR數字黨建展館更是成為引領紅色教育新風尚的重要載體。今天,就讓我們一起探討VR數字黨建展館如何提供沉浸式體驗,助力黨建工作創新升級…

十年OpenCV開發以后發布的作品 - OpenCV實驗大師

OpenCV介紹 OpenCV是知名的計算機視覺框架,支持數十個不同的視覺處理模塊,提供了超過2000多個傳統算法,其核心功能支持圖像處理、圖像分析、特征提取、對象檢測、深度學習模型推理等。當前支持C、Python、JS、C#等多種語言SDK,支…

智能優化算法應用:基于袋獾算法無線傳感器網絡(WSN)覆蓋優化 - 附代碼

智能優化算法應用:基于袋獾算法無線傳感器網絡(WSN)覆蓋優化 - 附代碼 文章目錄 智能優化算法應用:基于袋獾算法無線傳感器網絡(WSN)覆蓋優化 - 附代碼1.無線傳感網絡節點模型2.覆蓋數學模型及分析3.袋獾算法4.實驗參數設定5.算法結果6.參考文獻7.MATLAB…

雷達點云數據.pcd格式轉.bin格式

雷達點云數據.pcd格式轉.bin格式 注意,方法1原則上可行,但是本人沒整好pypcd的環境 方法2是絕對可以的。 方法1 1 源碼如下: def pcb2bin1(): # save as bin formatimport os# import pypcdfrom pypcd import pypcdimport numpy as np…

python pandas dataframe常用數據處理總結

最近一直在做數據處理相關的工作,有幾點經常遇到的情況總結如下: 數據中存在為空數據如何處理 處理方式1:丟棄數據行 # 實現方式1 data data.dropna(subset[id]) # 若id列中某行數值為空,丟棄整行數據 # 實現方式2 data df[df…

Ant Design Vue 年選擇器

文章目錄 參考文檔效果展示實現過程 參考文檔 提示:這里可以添加本文要記錄的大概內容: DatePicker 日期選擇框 大佬:搬磚小匠(Ant Design vue 只選擇年) 提示:以下是本篇文章正文內容,下面案…

光標雖小,但是能讓其憑空消失的原因不少,需要仔細檢查

在Windows 10中遇到鼠標光標有問題嗎?我們已經為你提供了所需的修復程序。 光標消失的原因 光標不斷消失可能是由各種原因引起的,因此有可能找到各種各樣的解決方案。光標可能根本無法工作,或者在特定情況下可能會消失。鼠標按鈕甚至可能在光標隱藏時工作。 以下是用戶注…

如何驗證一個URL是否合法

在JavaScript中,可以使用正則表達式(RegExp)或使用內置的URL對象來校驗一個URL。下面是一些常用的方法以及對應的代碼示例: 使用正則表達式進行校驗: function validateURL(url) {const pattern /^(https?:\/\/)?…

使用Caliper對Fabric地basic鏈碼進行性能測試

如果你需要對fabric網絡中地合約進行吞吐量、延遲等性能進行評估,可以使用Caliper來實現,會返回給你一份網頁版的直觀測試報告。下面是對test-network網絡地basic鏈碼地測試過程。 目錄 1. 建立caliper-workspace文件夾2. 安裝npm等3. calipe安裝4. 創建…

使用TransBigData組件實現個人手機定位功能

目錄 一、引言 二、技術背景 三、實現邏輯 四、代碼實現 五、優化與注意事項: 六、總結 摘要:隨著現代社會對定位服務的需求日益增加,實現個人手機定位功能成為了開發者的研究熱點。本文詳細闡述了如何使用Python和TransBigData組件實現…

Python 從入門到精通 學習筆記 Day03

Python 從入門到精通 第三天 今日目標 流程控制語句、退出循環、練習學習的內容 一、流程控制語句 流程控制的三種方式:順序語句、雙分支語句、循環語句 雙分支語句 Python 的雙分支語句使用if-else語句實現。 其語法結構如下: if條件:#如果條作為真&#xff…

Facebook廣告報告指標CPC

在Facebook廣告中,CPC可以作為一個關鍵指標來評估廣告效果和投資回報。較低的CPC意味著廣告主能以更低的價格獲得更多的點擊量,從而降低廣告投放成本。而較高的CPC可能暗示著廣告主需要更大的預算才能獲得相同數量的點擊。本文小編將講講Facebook廣告報告…

k8s上安裝KubeSphere

安裝KubeSphere 前置環境安裝nfs-server文件系統配置nfs-client配置默認存儲創建了一個存儲類metrics-server集群指標監控組件 安裝KubeSphere執行安裝查看安裝進度 前置環境 下載配置我都是以CentOS 7.9 安裝 k8s(詳細教程)文章的服務器作為示例,請自行修改為自己的…

2024年軟考科目怎么選?(選科指引)

新手在準備報考軟考時,都會遇到這樣的一個問題——科目這么多,我適合考什么?要想知道自己適合報什么科目,就需要了解每個科目是什么,考什么等一系列的問題。今天給大家分享一下。 軟考包含什么科目? 軟考…

facebook廣告相比谷歌廣告的優勢

Facebook廣告相比谷歌廣告的優勢主要體現在以下方面: 用戶數據豐富:Facebook擁有龐大的用戶數據,包括人口、興趣、行為等多個維度,這些數據可以幫助廣告主更準確地定位到目標受眾。相比之下,谷歌廣告的用戶數據相對較…

android快速網絡請求之android-networking

今天介紹一個知道的人不多的庫,寫個簡單的頁面什么的。用起來很爽?如果你疑惑那么多開源的網絡庫為啥不用? 因為這個簡單方便。拿來就用。經過這幾天的實踐。確實可以。推薦一下 如果你需要 GITHUB 首先。引入依賴 implementation com.ami…

MySQL 數據遷移要點

目錄 1. 相同版本的遷移 2. 不用版本的遷移 3. 不同數據庫的遷移 數據庫遷移就是把數據從一個系統移動到另一個系統上,遷移過程其實就是在源數據庫備份和目標數據庫恢復的過程組合。遷移的原因是多種多樣的,比如: 需要安裝新的數據庫服務…

elasticsearch中LessThen遇到的坑

開發中&#xff0c;使用到LessThen-小于某個參數的邏輯查詢&#xff0c;如下&#xff1a; /// <summary> /// 查詢狀態已發布&#xff08;狀態小于2&#xff09;的政策要聞分頁 /// </summary> /// <param name"input"></param> /// <re…

使用OkHttp上傳本地圖片及參數

下面以一個例子來講解在項目中如何使用OKHttp來對本地圖片做個最簡單的上傳功能&#xff0c;基本上無封裝&#xff0c;只需要簡單調用便可&#xff08;對于OKHttp的引入不再單獨做介紹&#xff09;。 1&#xff1a;構建上傳圖片附帶的參數&#xff08;params&#xff09; Map…