瀏覽器渲染原理 - 輸入url 回車后發生了什么

目錄

  • 渲染時間點
  • 渲染流水線
    • 1,解析(parse)HTML
      • 1.1,DOM樹
      • 1.2,CSSOM樹
      • 1.3,解析時遇到 css 是怎么做的
      • 1.4,解析時遇到 js 是怎么做的
    • 2,樣式計算 Recalculate style
    • 3,布局 layout
    • 4,分層 layer
    • 5,繪制 paint
    • 6,分塊 tiling
    • 7,光柵化 raster
    • 8,畫 draw
  • 常見面試題
    • 什么是 reflow
    • 什么是 repaint
    • 為什么 transform 效率高

在上一篇文章中,介紹了 瀏覽器的事件循環,其中提到了瀏覽器的進程模型。那瀏覽器是如何渲染頁面的呢?

渲染時間點

瀏覽器會通過網絡進程中的線程來通信,獲取到 html 數據后生成渲染任務,發送給消息隊列。

渲染主線程會執行渲染任務。整個渲染流程:把 html 字符串解析為像素點信息,再交給 GPU來渲染后在頁面中展示。

在這里插入圖片描述

渲染流水線

在這里插入圖片描述

每個階段都有明確的輸入輸出,上個階段的輸出會成為下個階段的輸入。形成一套完整的流水線。

1,解析(parse)HTML

會將 html 字符串解析為 2個樹。因為字符串不好操作,對象更容易處理。

1.1,DOM樹

也就是 document 對象。可以在控制臺通過console.dir(document) 展示對象結構。
在這里插入圖片描述

1.2,CSSOM樹

包括:

  • <style> 內部樣式
  • <link> 外部樣式
  • style="" 內聯樣式
  • 瀏覽器默認樣式表

在這里插入圖片描述

注意,這里的 CSSOM樹 ≠ document.styleSheets。因為 document.styleSheets 只包括內部樣式外部樣式,每寫一個 <style><link> 就會多一個 CSSStyleSheet 樣式表:

在這里插入圖片描述

舉例說明:

<html><head><style>body h1 {color: red;font-size: 3em;}div p {margin: 1em;color: blue;}</style></head><body><h1>下雪天的夏風</h1><div><p>求關注</p></div></body>
</html>

在這里插入圖片描述

可以看到:

  • CSSStyleSheet 樣式表
    • CSSStyleRule 規則對象
      • selectorText 選擇器
      • style 樣式(鍵值對)

另外,CSSStyleSheet 樣式表是可以直接通過 js 操作的。

舉例:通過 js 給頁面所有 div 添加 border

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

這樣添加樣式的方式,一般框架用的多。最終樣式不會在內聯樣式中展現。

1.3,解析時遇到 css 是怎么做的

渲染主線程遇到 css 時,會啟動一個預解析線程,讓它來率先下載和解析 css。渲染主線程繼續解析 html。

預解析線程會快速瀏覽,如果遇到外部樣式link ,會通知網絡線程來下載 css,下載完成后進行“解析”完成后交給渲染主線程。

并不是真正的解析,只是做一些前期工作,最終生成 CSSOM 樹還是由渲染主線程來完成。

所以,css 代碼不會阻塞解析 HTML。

在這里插入圖片描述

1.4,解析時遇到 js 是怎么做的

沒有生成所謂的 js 樹,是因為 js 只需要執行一遍即可。DOM樹和CSSOM樹作為解析 HTML 的輸出,后續還會有其他的操作。

渲染主線程遇到內部 js 時,直接啟動 V8 引擎執行即可;遇到外部 js 時,會啟動一個預解析線程,讓它來下載 js,渲染主線程暫停

預解析線程會通知網絡線程來下載 js,下載完成后再交給渲染主線程來執行。執行完繼續解析 HTML。

這樣做的原因:DOM 樹是邊解析邊生成的,而 js 代碼可能會修改之前已解析好的內容。

所以,js 代碼會阻塞解析 HTML。

在這里插入圖片描述

2,樣式計算 Recalculate style

遍歷DOM樹,計算每個節點的最終樣式 Computed Style。

這一過程,許多預設值會變成絕對值,比如 red 變為 rgb(255,0,0);相對單位變為絕對單位,比如rem 變為 px

最終會得到1個帶有最終樣式的 DOM 樹。
在這里插入圖片描述

可以在瀏覽器的 computed 窗口中,或使用 getComputedStyle() 查看某個元素的最終樣式。

3,布局 layout

遍歷DOM樹的每個節點,根據 css 屬性值計算每個節點的幾何信息(尺寸,相對包含塊的位置),生成一個 layout 樹。

注意到 DOM 樹和 layout 樹不一定一一對應。
在這里插入圖片描述
舉例1:diaplay:none 的元素不會出現在 layout 樹中。

問題來了,為什么<head> <link> 等元素默認是隱藏的?因為在瀏覽器默認樣式表中,它們 diaplay:none
在這里插入圖片描述
舉例2:偽元素的 content 內容在 DOM 樹中沒有,在 layout 樹中有。

在這里插入圖片描述
舉例3:內容必須在行盒中,行盒和塊盒不能相鄰。所以在 layout 樹中會有匿名塊盒

解釋:“行級元素”,“塊級元素”這些元素指的是 html。但元素的類型是 css 屬性決定的。所以稱為行盒或塊盒。

在這里插入圖片描述

4,分層 layer

現在 layout 布局樹中每個節點的幾何信息,尺寸位置等都明確了。渲染主線程會使用一套策略對整個布局樹分層。

目的是提升效率,這樣可以讓之后頁面的修改更新不會影響到其他層。類似 PS 中的圖層,修改某一個圖層不會影響到其他圖層。

可以在瀏覽器控制臺的 Layers 面板查看當前網頁的分層信息。
也不會分太多的層,因為會比較占內存。滾動條是單獨一層。

在這里插入圖片描述

另外,和堆疊上下文有關的 css 屬性(transform,opacity)會影響分層的決策。其中 will-change 屬性能更大程度的影響分層角色,可能會將設置該屬性的元素單獨分一層。

因為這個屬性會告訴瀏覽器,我可能會經常變化,瀏覽器最好掂量下。

5,繪制 paint

分層后,會對每層都生成繪制指令,類似于 canvas 中的 API 一樣。其實canvas 用的就是瀏覽器內核的繪制功能。

指令舉例:“筆”移動到 xx 坐標位置,畫 100*100 的矩形,并用紅色填充等等。

在這里插入圖片描述

以上。渲染主線程的工作結束,剩下的步驟交給其他線程來完成。

在這里插入圖片描述

6,分塊 tiling

將每層都分為多個小的區域,瀏覽器視窗區域的優先級最高,靠近視窗區域的優先級次之。
在這里插入圖片描述

分塊邏輯:渲染主線程每個圖層的繪制信息交給合成線程,合成線程又會啟動多個分塊線程來對每個圖層進行分塊。

合成線程也屬于渲染線程

在這里插入圖片描述

7,光柵化 raster

將每個塊變成位圖,位圖就是每個像素點的信息。優先處理靠近視窗的塊。

位圖就是內存中的二位數組,其中記錄了每個像素點的信息。

在這里插入圖片描述

此過程會用到GPU來加速,用到顯卡。
在這里插入圖片描述

8,畫 draw

合成線程現在拿到了所有的信息,在畫之前還需要確認【指引信息 quad】,也就是位圖相對的屏幕在哪里。

注意,之前布局樹中的信息是相對于整個頁面的。現在需要知道每個塊相對于屏幕的位置信息。

步驟:合成線程將指引信息 --> GPU 進程 --> 硬件顯卡,由顯卡來呈現最終的像素信息。

GPU 做中轉的原因是:GPU 是瀏覽器的進程。合成線程屬于渲染進程,它是在沙盒中的,與硬件系統做隔離,提升安全性。所以渲染進程是沒有調度系統硬件能力的。

在這里插入圖片描述
而 css 中的 transform 屬性就是在這一步完成的。這就是 transform 效率高的原因,直接跳過之前所有的步驟。

常見面試題

什么是 reflow

【recalculate layoutBlockFlow 重排】它的本質是重新計算 layout 樹

當做了會影響 layout 樹的操作后,比如修改幾何尺寸相關的信息時,會引起重新計算 layout 樹。

在這里插入圖片描述

并且,為了避免連續多次的操作導致 layout 樹反復計算,瀏覽器會合并這些操作,當 js 代碼完成后統一計算。所以這一步驟是異步的。

同樣因為這個原因,當 js 獲取布局屬性時,可能無法獲取到最新的布局信息。

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

什么是 repaint

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

當改變了可見樣式,比如顏色等和幾何尺寸無關的屬性時,就需要重新計算,會從【繪制】這一步驟開始重新執行。

而因為幾何尺寸也屬于可見樣式,所以 reflow 一定會引起 repaint。

在這里插入圖片描述

為什么 transform 效率高

因為 transform 既不會影響布局,也不會影響繪制,它只會影響渲染的最后一步【畫】。而【畫】是在合成線程中,不會影響到渲染主線程。同樣無論渲染主線程多忙,也不會影響到 transform。

驗證代碼如下,當渲染主線程卡死時,transform 不受影響。

<!DOCTYPE html>
<html lang="en"><head><style>.common {width: 50px;height: 50px;background-color: salmon;border-radius: 50%;margin: 10px;}.ball1 {animation: move1 1s alternate infinite;}.ball2 {position: relative;left: 0;animation: move2 1s alternate infinite;}@keyframes move1 {to {transform: translate(100px);}}@keyframes move2 {to {left: 100px;}}</style></head><body><button id="btn">死循環3s</button><div class="common ball1"></div><div class="common ball2"></div><script>btn.addEventListener("click", function () {delay(3000);});function delay(duration) {var start = Date.now();while (Date.now() - start < duration) {}}</script></body>
</html>

效果:
在這里插入圖片描述

滾動也是一樣的邏輯,如果 js 有一段上面的死循環,并不會影響到滾動。因為只有視窗內元素的位置變了,直接執行【畫 draw】這一步驟。

以上。


參考:渡一教育。

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

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

相關文章

創建react native項目的筆記

創建react native項目的筆記 重新下載 ruby安裝 watchman安裝 cocoapods安裝 react native 項目創建好項目后安裝 ios 依賴清除設備緩存安裝 android 依賴鏈接 網易 mumu 模擬器安裝路由 Navigation頁面之間的跳轉邏輯自定義頭部樣式判斷不同設備平臺代碼示例安裝 Axios安裝本地…

java mysql druid mybatis-plus里使用多表刪除出錯的一種處理方式

今天在出來多表刪除的時候在mapper.xml用了下面的多個delete語句 <?xml version"1.0" encoding"UTF-8"?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"…

Spring Cloud 系列之OpenFeign:(7)鏈路追蹤zipkin

傳送門 Spring Cloud Alibaba系列之nacos&#xff1a;(1)安裝 Spring Cloud Alibaba系列之nacos&#xff1a;(2)單機模式支持mysql Spring Cloud Alibaba系列之nacos&#xff1a;(3)服務注冊發現 Spring Cloud 系列之OpenFeign&#xff1a;(4)集成OpenFeign Spring Cloud …

PHP酒店點菜管理系統mysql數據庫web結構apache計算機軟件工程網頁wamp

一、源碼特點 PHP 酒店點菜管理系統是一套完善的web設計系統&#xff0c;對理解php編程開發語言有幫助&#xff0c;系統具有完整的源代碼和數據庫&#xff0c;系統主要采用B/S模式開發。 代碼下載 https://download.csdn.net/download/qq_41221322/88232051 論文 https://…

前端技術Vue學習筆記--005

Vue學習筆記 一、非父子通信-event bus 事件總線 作用&#xff1a;非父子組件之間&#xff0c;進行簡易消息傳遞。&#xff08;復雜場景用----Vuex&#xff09; 使用步驟&#xff1a; 創建一個都能訪問的事件總線 &#xff08;空Vue實例&#xff09;-----utils/EventBus.js /…

兩個數組的交集-C語言/Java

描述 給定兩個數組 nums1 和 nums2 &#xff0c;返回 它們的交集 。輸出結果中的每個元素一定是 唯一 的。我們可以 不考慮輸出結果的順序。&#xff08;1 < nums1.length, nums2.length < 1000&#xff0c;0 < nums1[i], nums2[i] < 1000&#xff09; 示例1 輸入…

【golang】通道(channel)的基本原理(一)

通道類型的值本身就是并發安全的&#xff0c;這也是Go語言自帶的、唯一一個可以滿足并發安全性的類型。 聲明一個通道類型變量的時候&#xff0c;我們首先要確定該通道類型的元素類型&#xff0c;決定了我們可以通過這個通道傳遞什么類型的數據。 在初始化通道的時候&#xf…

一鍵批量修改文件夾名稱,中文瞬間變日語,輕松搞定重命名

大家好&#xff01;現在為了更好地適應全球化發展&#xff0c;許多人都有了海外交流、旅行、學習的需求。但是難免遇到一個問題&#xff1a;在電腦中的中文文件夾名稱如何快速翻譯成日語&#xff1f; 首先&#xff0c;第一步&#xff0c;我們需要打開文件批量改名&#xff0c;…

【Unity】編輯器下查找制定文件下的所有特定資源

需求上很簡單&#xff0c;就是在編輯器下&#xff0c;找到某個制定文件下的所有特定資源&#xff08;UnityEngine.Object&#xff09;。Unity 沒有提供專門的 API&#xff0c;我一開始想在網上搜索代碼&#xff0c;發現沒有現成可以直接用的。 功能實現本身并不復雜&#xff0c…

AWS EKS 集群自動擴容 Cluster Autoscaler

文章目錄 一&#xff0c;需求工作需求說明 二&#xff0c;部署精簡命令執行1&#xff0c;要求2&#xff0c;查看EC2 Auto Scaling groups Tag3&#xff0c;創建Serviceaccount需要的Policy&#xff0c;Role4&#xff0c;部署Cluster Autoscaler5&#xff0c;驗證6&#xff0c;常…

zotero在不同系統的安裝(win/linux)

1 window系統安裝 zotero 官網&#xff1a; https://www.zotero.org/ 官方文檔 &#xff1a;https://www.zotero.org/support/ (官方)推薦常用的插件: https://www.zotero.org/support/plugins 入門視頻推薦&#xff1a; Zotero 文獻管理與知識整理最佳實踐 點擊 exe文件自…

【環境配置】Windows 10 安裝 PyTorch 開發環境,以及驗證 YOLOv8

Windows 10 安裝 PyTorch 開發環境&#xff0c;以及驗證 YOLOv8 最近搞了一臺Windows機器&#xff0c;準備在上面安裝深度學習的開發環境&#xff0c;并搭建部署YOLOv8做訓練和測試使用&#xff1b; 環境&#xff1a; OS&#xff1a; Windows 10 顯卡&#xff1a; RTX 3090 安…

Bug日記-webstorm運行yarn 命令報錯

在windows中輸入yarn -v正確輸出&#xff0c;在webstrom終端中運行yarn命令輸出錯誤 問題&#xff1a;可能是由于 WebStorm 配置問題導致的。 解決方案&#xff1a; 檢查 WebStorm 的終端配置&#xff1a;在 WebStorm 中&#xff0c;點擊菜單欄的 “File”&#xff08;文件&am…

DeepSort:基于檢測的目標跟蹤的經典

本文來自公眾號“AI大道理” DeepSORT在SORT的基礎上引入了深度學習的特征表示和更強大的目標關聯方式&#xff0c;有效地減少了身份切換的數量&#xff0c;緩解了重識別問題。 ? 1、DeepSORT簡介 DeepSORT的主要思想是將目標檢測和目標跟蹤兩個任務相結合。 首先使用目標檢…

排序算法分析——什么時候 用 什么排序

排序算法 & 分析 排序算法歷史排序算法分析很快的排序較快的排序中等的排序很慢的排序 分析的結果0.沒有要求1.對速度有要求2.邊排序邊操作3.條件1&條件24.在有序數中操作5.條件1&條件4 了解各種排序&#xff0c;詳見排序專欄 排序算法歷史 縱觀排序算法的歷史&a…

硬件產品經理:從入門到精通(新書發布)

目錄 簡介 新書 框架內容 相關課程 簡介 在完成多款硬件產品從設計到推向市場的過程后。 筆者于2020年開始在產品領域平臺輸出硬件相關的內容。 在這個過程中經常會收到很多讀者的留言&#xff0c;希望能推薦一些硬件相關的書籍或資料。 其實&#xff0c;筆者剛開始做硬…

10. 實現業務功能--退出登錄

目錄 1. 實現 Controller 2. 單體測試 3. 實現前端界面 退出的具體實現邏輯如下&#xff1a; 1. 用戶訪問退出接口 2. 服務器注銷 Session( 在 Controller 中可以直接進行處理 &#xff09; 3. 返回成功或失敗 4. 如果返回成功瀏覽器跳轉到相應頁面 5. 結束 一般來說&#…

使用VS2015打開.pro文件后,編譯報錯

編譯報錯內容&#xff1a; MSB8036 找不到 Windows SDK 版本10.0.18362.0。請安裝所需的版本的 Windows SDK 或者在項目屬性頁中或通過右鍵單擊解決方案并選擇“重定解決方案目標”來更改 SD 方法&#xff1a; 1.右鍵點擊 Solution上&#xff0c;在彈出的框中點擊“Retarget…

調整數組使奇數全部都位于偶數前面

題目內容&#xff1a; 輸入一個整數數組&#xff0c;實現一個函數&#xff0c; 來調整該數組中數字的順序使得數組中所有的奇數位于數組的前半部分&#xff0c; 所有偶數位于數組的后半部分。 題目思路&#xff1a; 將奇數部分放在前半部分&#xff0c;偶數部分放在后半部分&am…