<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          【優(yōu)化】1141- 網頁渲染性能優(yōu)化 —— 渲染原理

          共 13850字,需瀏覽 28分鐘

           ·

          2021-11-15 20:34


          作者:晨風明悟

          鏈接:https://zhuanlan.zhihu.com/p/39879808

          渲染原理

          在討論性能優(yōu)化之前,我們有必要了解一些瀏覽器的渲染原理。不同的瀏覽器進行渲染有著不同的實現(xiàn)方式,但是大體流程都是差不多的,我們通過 Chrome 瀏覽器來大致了解一下這個渲染流程。

          關鍵渲染路徑

          關鍵渲染路徑是指瀏覽器將 HTML、CSS 和 JavaScript 轉換成實際運作的網站必須采取的一系列步驟,通過渲染流程圖我們可以大致概括如下:

          1. 處理 HTML 并構建 DOM Tree。
          2. 處理 CSS 并構建 CSSOM Tree。
          3. 將 DOM Tree 和 CSSOM Tree 合并成 Render Object Tree。
          4. 根據(jù) Render Object Tree 計算節(jié)點的幾何信息并以此進行布局。
          5. 繪制頁面需要先構建 Render Layer Tree 以便用正確的順序展示頁面,這棵樹的生成與 Render Object Tree 的構建同步進行。然后還要構建 Graphics Layer Tree 來避免不必要的繪制和使用硬件加速渲染,最終才能在屏幕上展示頁面。

          DOM Tree

          DOM(Document Object Model——文檔對象模型)是用來呈現(xiàn)以及與任意 HTML 或 XML 交互的 API 文檔。DOM 是載入到瀏覽器中的文檔模型,它用節(jié)點樹的形式來表現(xiàn)文檔,每個節(jié)點代表文檔的構成部分。

          需要說明的是 DOM 只是構建了文檔標記的屬性和關系,并沒有說明元素需要呈現(xiàn)的樣式,這需要 CSSOM 來處理。

          構建流程

          獲取到 HTML 字節(jié)數(shù)據(jù)后,會通過以下流程構建 DOM Tree:

          1. 編碼:HTML 原始字節(jié)數(shù)據(jù)轉換為文件指定編碼的字符串。
          2. 詞法分析(標記化):對輸入字符串進行逐字掃描,根據(jù) 構詞規(guī)則 識別單詞和符號,分割成一個個我們可以理解的詞匯(學名叫 Token )的過程。
          3. 語法分析(解析器):對 Tokens 應用 HTML 的語法規(guī)則,進行配對標記、確立節(jié)點關系和綁定屬性等操作,從而構建 DOM Tree 的過程。

          詞法分析和語法分析在每次處理 HTML 字符串時都會執(zhí)行這個過程,比如使用 document.write 方法。

          詞法分析(標記化)

          HTML 結構不算太復雜,大部分情況下識別的標記會有開始標記、內容標記和結束標記,對應一個 HTML 元素。除此之外還有 DOCTYPE、Comment、EndOfFile 等標記。

          標記化是通過狀態(tài)機來實現(xiàn)的,狀態(tài)機模型在 W3C 中已經定義好了。

          想要得到一個標記,必須要經歷一些狀態(tài),才能完成解析。我們通過一個簡單的例子來了解一下流程。

          W3C
          • 開始標記:
          • Data state:碰到 <,進入 Tag open state
          • Tag open state:碰到 a,進入 Tag name state 狀態(tài)
          • Tag name state:碰到 空格,進入 Before attribute name state
          • Before attribute name state:碰到 h,進入 Attribute name state
          • Attribute name state:碰到 =,進入 Before attribute value state
          • Before attribute value state:碰到 ",進入 Attribute value (double-quoted) state
          • Attribute value (double-quoted) state:碰到 w,保持當前狀態(tài)
          • Attribute value (double-quoted) state:碰到 ",進入 After attribute value (quoted) state
          • After attribute value (quoted) state:碰到 >,進入 Data state,完成解析
          • 內容標記:W3C
          • Data state:碰到 W,保持當前狀態(tài),提取內容
          • Data state:碰到 <,進入 Tag open state,完成解析
          • 結束標記:
          • Tag open state:碰到 /,進入 End tag open state
          • End tag open state:碰到 a,進入 Tag name state
          • Tag name state:碰到 >,進入 Data state,完成解析

          通過上面這個例子,可以發(fā)現(xiàn)屬性是開始標記的一部分。

          語法分析(解析器)

          在創(chuàng)建解析器后,會關聯(lián)一個 Document 對象作為根節(jié)點。

          我會簡單介紹一下流程,具體的實現(xiàn)過程可以在 Tree construction 查看。

          解析器在運行過程中,會對 Tokens 進行迭代;并根據(jù)當前 Token 的類型轉換到對應的模式,再在當前模式下處理 Token;此時,如果 Token 是一個開始標記,就會創(chuàng)建對應的元素,添加到 DOM Tree 中,并壓入還未遇到結束標記的開始標記棧中;此棧的主要目的是實現(xiàn)瀏覽器的容錯機制,糾正嵌套錯誤,具體的策略在 W3C 中定義。更多標記的處理可以在 狀態(tài)機算法 中查看。

          參考資料

          1. 瀏覽器的工作原理:新式網絡瀏覽器幕后揭秘 —— 解析器和詞法分析器的組合
          2. 瀏覽器渲染過程與性能優(yōu)化 —— 構建DOM樹與CSSOM樹
          3. 在瀏覽器的背后(一) —— HTML語言的詞法解析
          4. 在瀏覽器的背后(二) —— HTML語言的語法解析
          5. 50 行代碼的 HTML 編譯器
          6. AST解析基礎: 如何寫一個簡單的html語法分析庫
          7. WebKit中的HTML詞法分析
          8. HTML文檔解析和DOM樹的構建
          9. 從Chrome源碼看瀏覽器如何構建DOM樹
          10. 構建對象模型 —— 文檔對象模型 (DOM)

          CSSOM Tree

          加載

          在構建 DOM Tree 的過程中,如果遇到 link 標記,瀏覽器就會立即發(fā)送請求獲取樣式文件。當然我們也可以直接使用內聯(lián)樣式或嵌入樣式,來減少請求;但是會失去模塊化和可維護性,并且像緩存和其他一些優(yōu)化措施也無效了,利大于弊,性價比實在太低了;除非是為了極致優(yōu)化首頁加載等操作,否則不推薦這樣做。

          阻塞

          CSS 的加載和解析并不會阻塞 DOM Tree 的構建,因為 DOM Tree 和 CSSOM Tree 是兩棵相互獨立的樹結構。但是這個過程會阻塞頁面渲染,也就是說在沒有處理完 CSS 之前,文檔是不會在頁面上顯示出來的,這個策略的好處在于頁面不會重復渲染;如果 DOM Tree 構建完畢直接渲染,這時顯示的是一個原始的樣式,等待 CSSOM Tree 構建完畢,再重新渲染又會突然變成另外一個模樣,除了開銷變大之外,用戶體驗也是相當差勁的。另外 link 標記會阻塞 JavaScript 運行,在這種情況下,DOM Tree 是不會繼續(xù)構建的,因為 JavaScript 也會阻塞 DOM Tree 的構建,這就會造成很長時間的白屏。

          通過一個例子來更加詳細的說明:










          性能


          標題


          標題2




          首先需要在 Chrome 控制臺的 Network 面板設置網絡節(jié)流,讓網絡速度變慢,以便更好進行調試。

          下圖說明 JavaScript 的確需要在 CSS 加載并解析完畢之后才會執(zhí)行。

          為什么需要阻塞 JavaScript 的運行呢?

          因為 JavaScript 可以操作 DOM 和 CSSOM,如果 link 標記不阻塞 JavaScript 運行,這時 JavaScript 操作 CSSOM,就會發(fā)生沖突。更詳細的說明可以在 使用 JavaScript 添加交互 這篇文章中查閱。

          解析

          CSS 解析的步驟與 HTML 的解析是非常類似的。

          詞法分析

          CSS 會被拆分成如下一些標記:

          CSS 的色值使用十六進制優(yōu)于函數(shù)形式的表示?

          函數(shù)形式是需要再次計算的,在進行詞法分析時會將它變成一個函數(shù)標記,由此看來使用十六進制的確有所優(yōu)化。

          語法分析

          每個 CSS 文件或嵌入樣式都會對應一個 CSSStyleSheet 對象(authorStyleSheet),這個對象由一系列的 Rule(規(guī)則) 組成;每一條 Rule 都會包含 Selectors(選擇器) 和若干 Declearation(聲明),Declearation 又由 Property(屬性)和 Value(值)組成。另外,瀏覽器默認樣式表(defaultStyleSheet)和用戶樣式表(UserStyleSheet)也會有對應的 CSSStyleSheet 對象,因為它們都是單獨的 CSS 文件。至于內聯(lián)樣式,在構建 DOM Tree 的時候會直接解析成 Declearation 集合。

          內聯(lián)樣式和 authorStyleSheet 的區(qū)別

          所有的 authorStyleSheet 都掛載在 document 節(jié)點上,我們可以在瀏覽器中通過 document.styleSheets 獲取到這個集合。內聯(lián)樣式可以直接通過節(jié)點的 style 屬性查看。

          通過一個例子,來了解下內聯(lián)樣式和 authorStyleSheet 的區(qū)別:










          Document


          test



          可以看到一共有三個 CSSStyleSheet 對象,每個 CSSStyleSheet 對象的 rules 里面會有一個 CSSStyleDeclaration,而內聯(lián)樣式獲取到的直接就是 CSSStyleDeclaration。

          需要屬性合并嗎?

          在解析 Declearation 時遇到屬性合并,會把單條聲明轉變成對應的多條聲明,比如:

          .box {
          margin: 20px;
          }

          margin: 20px 就會被轉變成四條聲明;這說明 CSS 雖然提倡屬性合并,但是最終還是會進行拆分的;所以屬性合并的作用應該在于減少 CSS 的代碼量。

          計算

          為什么需要計算?

          因為一個節(jié)點可能會有多個 Selector 命中它,這就需要把所有匹配的 Rule 組合起來,再設置最后的樣式。

          準備工作

          為了便于計算,在生成 CSSStyleSheet 對象后,會把 CSSStyleSheet 對象最右邊 Selector 類型相同的 Rules 存放到對應的 Hash Map 中,比如說所有最右邊 Selector 類型是 id 的 Rules 就會存放到 ID Rule Map 中;使用最右邊 Selector 的原因是為了更快的匹配當前元素的所有 Rule,然后每條 Rule 再檢查自己的下一個 Selector 是否匹配當前元素。

          idRules
          classRules
          tagRules
          ...
          *

          選擇器命中

          一個節(jié)點想要獲取到所有匹配的 Rule,需要依次判斷 Hash Map 中的 Selector 類型(id、class、tagName 等)是否匹配當前節(jié)點,如果匹配就會篩選當前 Selector 類型的所有 Rule,找到符合的 Rule 就會放入結果集合中;需要注意的是通配符總會在最后進行篩選。

          從右向左匹配規(guī)則

          上文說過 Hash Map 存放的是最右邊 Selector 類型的 Rule,所以在查找符合的 Rule 最開始,檢驗的是當前 Rule 最右邊的 Selector;如果這一步通過,下面就要判斷當前的 Selector 是不是最左邊的 Selector;如果是,匹配成功,放入結果集合;否則,說明左邊還有 Selector,遞歸檢查左邊的 Selector 是否匹配,如果不匹配,繼續(xù)檢查下一個 Rule。

          為什么需要從右向左匹配呢?

          先思考一下正向匹配是什么流程,我們用 div p .yellow 來舉例,先查找所有 div 節(jié)點,再向下查找后代是否是 p 節(jié)點,如果是,再向下查找是否存在包含 class="yellow" 的節(jié)點,如果存在則匹配;但是不存在呢?就浪費一次查詢,如果一個頁面有上千個 div 節(jié)點,而只有一個節(jié)點符合 Rule,就會造成大量無效查詢,并且如果大多數(shù)無效查詢都在最后發(fā)現(xiàn),那損失的性能就實在太大了。

          這時再思考從右向左匹配的好處,如果一個節(jié)點想要找到匹配的 Rule,會先查詢最右邊 Selector 是當前節(jié)點的 Rule,再向左依次檢驗 Selector;在這種匹配規(guī)則下,開始就能避免大多無效的查詢,當然性能就更好,速度更快了。

          設置樣式

          設置樣式的順序是先繼承父節(jié)點,然后使用用戶代理的樣式,最后使用開發(fā)者(authorStyleSheet)的樣式。

          authorStyleSheet 優(yōu)先級

          放入結果集合的同時會計算這條 Rule 的優(yōu)先級;來看看 blink 內核對優(yōu)先級權重的定義:

          switch (m_match) {
          case Id:
          return 0x010000;
          case PseudoClass:
          return 0x000100;
          case Class:
          case PseudoElement:
          case AttributeExact:
          case AttributeSet:
          case AttributeList:
          case AttributeHyphen:
          case AttributeContain:
          case AttributeBegin:
          case AttributeEnd:
          return 0x000100;
          case Tag:
          return 0x000001;
          case Unknown:
          return 0;
          }
          return 0;

          因為解析 Rule 的順序是從右向左進行的,所以計算優(yōu)先級也會按照這個順序取得對應 Selector 的權重后相加。來看幾個例子:

          /*
          * 65793 = 65536 + 1 + 256
          */
          #container p .text {
          font-size: 16px;
          }

          /*
          * 2 = 1 + 1
          */
          div p {
          font-size: 14px;
          }

          當前節(jié)點所有匹配的 Rule 都放入結果集合之后,先根據(jù)優(yōu)先級從小到大排序,如果有優(yōu)先級相同的 Rule,則比較它們的位置。

          內聯(lián)樣式優(yōu)先級

          authorStyleSheet 的 Rule 處理完畢,才會設置內聯(lián)樣式;內聯(lián)樣式在構建 DOM Tree 的時候就已經處理完成并存放到節(jié)點的 style 屬性上了。

          內聯(lián)樣式會放到已經排序的結果集合最后,所以如果不設置 !important,內聯(lián)樣式的優(yōu)先級是最大的。

          !important 優(yōu)先級

          在設置 !important 的聲明前,會先設置不包含 !important 的所有聲明,之后再添加到結果集合的尾部;因為這個集合是按照優(yōu)先級從小到大排序好的,所以 !important 的優(yōu)先級就變成最大的了。

          書寫 CSS 的規(guī)則

          結果集合最后會生成 ComputedStyle 對象,可以通過 window.getComputedStyle 方法來查看所有聲明。

          可以發(fā)現(xiàn)圖中的聲明是沒有順序的,說明書寫規(guī)則的最大作用是為了良好的閱讀體驗,利于團隊協(xié)作。

          調整 Style

          這一步會調整相關的聲明;例如聲明了 position: absolute;,當前節(jié)點的 display 就會設置成 block。

          參考資料

          1. 從Chrome源碼看瀏覽器如何計算CSS
          2. 探究 CSS 解析原理
          3. Webkit內核探究【2】——Webkit CSS實現(xiàn)
          4. Webkit CSS引擎分析
          5. css加載會造成阻塞嗎?
          6. 原來 CSS 與 JS 是這樣阻塞 DOM 解析和渲染的
          7. 外鏈 CSS 延遲 DOM 解析和 DOMContentLoaded
          8. CSS/JS 阻塞 DOM 解析和渲染
          9. 構建對象模型 —— CSS 對象模型 (CSSOM)
          10. 阻塞渲染的 CSS

          Render Object Tree

          在 DOM Tree 和 CSSOM Tree 構建完畢之后,才會開始生成 Render Object Tree(Document 節(jié)點是特例)。

          創(chuàng)建 Render Object

          在創(chuàng)建 Document 節(jié)點的時候,會同時創(chuàng)建一個 Render Object 作為樹根。Render Object 是一個描述節(jié)點位置、大小等樣式的可視化對象。

          每個非 display: none | contents 的節(jié)點都會創(chuàng)建一個 Render Object,流程大致如下:生成 ComputedStyle(在 CSSOM Tree 計算這一節(jié)中有講),之后比較新舊 ComputedStyle(開始時舊的 ComputedStyle 默認是空);不同則創(chuàng)建一個新的 Render Object,并與當前處理的節(jié)點關聯(lián),再建立父子兄弟關系,從而形成一棵完整的 Render Object Tree。

          布局(重排)

          Render Object 在添加到樹之后,還需要重新計算位置和大小;ComputedStyle 里面已經包含了這些信息,為什么還需要重新計算呢?因為像 margin: 0 auto; 這樣的聲明是不能直接使用的,需要轉化成實際的大小,才能通過繪圖引擎繪制節(jié)點;這也是 DOM Tree 和 CSSOM Tree 需要組合成 Render Object Tree 的原因之一。

          布局是從 Root Render Object 開始遞歸的,每一個 Render Object 都有對自身進行布局的方法。為什么需要遞歸(也就是先計算子節(jié)點再回頭計算父節(jié)點)計算位置和大小呢?因為有些布局信息需要子節(jié)點先計算,之后才能通過子節(jié)點的布局信息計算出父節(jié)點的位置和大小;例如父節(jié)點的高度需要子節(jié)點撐起。如果子節(jié)點的寬度是父節(jié)點高度的 50%,要怎么辦呢?這就需要在計算子節(jié)點之前,先計算自身的布局信息,再傳遞給子節(jié)點,子節(jié)點根據(jù)這些信息計算好之后就會告訴父節(jié)點是否需要重新計算。

          數(shù)值類型

          所有相對的測量值(rem、em、百分比...)都必須轉換成屏幕上的絕對像素。如果是 em 或 rem,則需要根據(jù)父節(jié)點或根節(jié)點計算出像素。如果是百分比,則需要乘以父節(jié)點寬或高的最大值。如果是 auto,需要用 (父節(jié)點的寬或高 - 當前節(jié)點的寬或高) / 2 計算出兩側的值。

          盒模型

          眾所周知,文檔的每個元素都被表示為一個矩形的盒子(盒模型),通過它可以清晰的描述 Render Object 的布局結構;在 blink 的源碼注釋中,已經生動的描述了盒模型,與原先耳熟能詳?shù)牟煌瑵L動條也包含在了盒模型中,但是滾動條的大小并不是所有的瀏覽器都能修改的。

          // ***** THE BOX MODEL *****
          // The CSS box model is based on a series of nested boxes:
          // http://www.w3.org/TR/CSS21/box.html
          // top
          // |----------------------------------------------------|
          // | |
          // | margin-top |
          // | |
          // | |-----------------------------------------| |
          // | | | |
          // | | border-top | |
          // | | | |
          // | | |--------------------------|----| | |
          // | | | | | | |
          // | | | padding-top |####| | |
          // | | | |####| | |
          // | | | |----------------| |####| | |
          // | | | | | | | | |
          // left | ML | BL | PL | content box | PR | SW | BR | MR |
          // | | | | | | | | |
          // | | | |----------------| | | | |
          // | | | | | | |
          // | | | padding-bottom | | | |
          // | | |--------------------------|----| | |
          // | | | ####| | | |
          // | | | scrollbar height ####| SC | | |
          // | | | ####| | | |
          // | | |-------------------------------| | |
          // | | | |
          // | | border-bottom | |
          // | | | |
          // | |-----------------------------------------| |
          // | |
          // | margin-bottom |
          // | |
          // |----------------------------------------------------|
          //
          // BL = border-left
          // BR = border-right
          // ML = margin-left
          // MR = margin-right
          // PL = padding-left
          // PR = padding-right
          // SC = scroll corner (contains UI for resizing (see the 'resize' property)
          // SW = scrollbar width

          box-sizing

          box-sizing: content-box | border-box,content-box 遵循標準的 W3C 盒子模型,border-box 遵守 IE 盒子模型。

          它們的區(qū)別在于 content-box 只包含 content area,而 border-box 則一直包含到 border。通過一個例子說明:

          // width
          // content-box: 40
          // border-box: 40 + (2 * 2) + (1 * 2)
          div {
          width: 40px;
          height: 40px;
          padding: 2px;
          border: 1px solid #ccc;
          }

          參考資料

          1. 從Chrome源碼看瀏覽器如何layout布局
          2. Chromium網頁Render Object Tree創(chuàng)建過程分析
          3. 瀏覽器的工作原理:新式網絡瀏覽器幕后揭秘 —— 呈現(xiàn)樹和 DOM 樹的關系
          4. 談談我對盒模型的理解
          5. 渲染樹構建、布局及繪制

          Render Layer Tree

          Render Layer 是在 Render Object 創(chuàng)建的同時生成的,具有相同坐標空間的 Render Object 屬于同一個 Render Layer。這棵樹主要用來實現(xiàn)層疊上下文,以保證用正確的順序合成頁面。

          創(chuàng)建 Render Layer

          滿足層疊上下文條件的 Render Object 一定會為其創(chuàng)建新的 Render Layer,不過一些特殊的 Render Object 也會創(chuàng)建一個新的 Render Layer。

          創(chuàng)建 Render Layer 的原因如下:

          • NormalLayer
          • position 屬性為 relative、fixed、sticky、absolute
          • 透明的(opacity 小于 1)、濾鏡(filter)、遮罩(mask)、混合模式(mix-blend-mode 不為 normal)
          • 剪切路徑(clip-path)
          • 2D 或 3D 轉換(transform 不為 none)
          • 隱藏背面(backface-visibility: hidden)
          • 倒影(box-reflect)
          • column-count(不為 auto)或者column-widthZ(不為 auto)
          • 對不透明度(opacity)、變換(transform)、濾鏡(filter)應用動畫
          • OverflowClipLayer
          • 剪切溢出內容(overflow: hidden)

          另外以下 DOM 元素對應的 Render Object 也會創(chuàng)建單獨的 Render Layer:

          • Document
          • HTML
          • Canvas
          • Video

          如果是 NoLayer 類型,那它并不會創(chuàng)建 Render Layer,而是與其第一個擁有 Render Layer 的父節(jié)點共用一個。

          參考資料

          1. 無線性能優(yōu)化:Composite —— 從 LayoutObjects 到 PaintLayers
          2. Chromium網頁Render Layer Tree創(chuàng)建過程分析
          3. WEBKIT 渲染不可不知的這四棵樹

          Graphics Layer Tree

          軟件渲染

          軟件渲染是瀏覽器最早采用的渲染方式。在這種方式中,渲染是從后向前(遞歸)繪制 Render Layer 的;在繪制一個 Render Layer 的過程中,它的 Render Objects 不斷向一個共享的 Graphics Context 發(fā)送繪制請求來將自己繪制到一張共享的位圖中。

          硬件渲染

          有些特殊的 Render Layer 會繪制到自己的后端存儲(當前 Render Layer 會有自己的位圖),而不是整個網頁共享的位圖中,這些 Layer 被稱為 Composited Layer(Graphics Layer)。最后,當所有的 Composited Layer 都繪制完成之后,會將它們合成到一張最終的位圖中,這一過程被稱為 Compositing;這意味著如果網頁某個 Render Layer 成為 Composited Layer,那整個網頁只能通過合成來渲染。除此之外,Compositing 還包括 transform、scale、opacity 等操作,所以這就是硬件加速性能好的原因,上面的動畫操作不需要重繪,只需要重新合成就好。

          上文提到軟件渲染只會有一個 Graphics Context,并且所有的 Render Layer 都會使用同一個 Graphics Context 繪制。而硬件渲染需要多張位圖合成才能得到一張完整的圖像,這就需要引入 Graphics Layer Tree。

          Graphics Layer Tree 是根據(jù) Render Layer Tree 創(chuàng)建的,但并不是每一個 Render Layer 都會有對應的 Composited Layer;這是因為創(chuàng)建大量的 Composited Layer 會消耗非常多的系統(tǒng)內存,所以 Render Layer 想要成為 Composited Layer,必須要給出創(chuàng)建的理由,這些理由實際上就是在描述 Render Layer 具備的特征。如果一個 Render Layer 不是 Compositing Layer,那就和它的祖先共用一個。

          每一個 Graphics Layer 都會有對應的 Graphics Context。Graphics Context 負責輸出當前 Render Layer 的位圖,位圖存儲在系統(tǒng)內存中,作為紋理(可以理解為 GPU 中的位圖)上傳到 GPU 中,最后 GPU 將多張位圖合成,然后繪制到屏幕上。因為 Graphics Layer 會有單獨的位圖,所以在一般情況下更新網頁的時候硬件渲染不像軟件渲染那樣重新繪制相關的 Render Layer;而是重新繪制發(fā)生更新的 Graphics Layer。

          提升原因

          Render Layer 提升為 Composited Layer 的理由大致概括如下,更為詳細的說明可以查看 無線性能優(yōu)化:Composite —— 從 PaintLayers 到 GraphicsLayers。

          • iframe 元素具有 Composited Layer。
          • video 元素及它的控制欄。
          • 使用 WebGL 的 canvas 元素。
          • 硬件加速插件,例如 flash。
          • 3D 或透視變換(perspective transform) CSS 屬性。
          • backface-visibility 為 hidden。
          • 對 opacity、transform、fliter、backdropfilter 應用了 animation 或者 transition(需要是 active 的 animation 或者 transition,當 animation 或者 transition 效果未開始或結束后,提升的 Composited Layer 會恢復成普通圖層)。
          • will-change 設置為 opacity、transform、top、left、bottom、right(其中 top、left 等需要設置明確的定位屬性,如 relative 等)。
          • 有 Composited Layer 后代并本身具有某些屬性。
          • 元素有一個 z-index 較低且為 Composited Layer 的兄弟元素。

          為什么需要 Composited Layer?

          1. 避免不必要的重繪。例如網頁中有兩個 Layer a 和 b,如果 a Layer 的元素發(fā)生改變,b Layer 沒有發(fā)生改變;那只需要重新繪制 a Layer,然后再與 b Layer 進行 Compositing,就可以得到整個網頁。
          2. 利用硬件加速高效實現(xiàn)某些 UI 特性。例如滾動、3D 變換、透明度或者濾鏡效果,可以通過 GPU(硬件渲染)高效實現(xiàn)。

          層壓縮

          由于重疊的原因,可能會產生大量的 Composited Layer,就會浪費很多資源,嚴重影響性能,這個問題被稱為層爆炸。瀏覽器通過 Layer Squashing(層壓縮)處理這個問題,當有多個 Render Layer 與 Composited Layer 重疊,這些 Render Layer 會被壓縮到同一個 Composited Layer。來看一個例子:








          Document







          可以看到后面兩個節(jié)點重疊而壓縮到了同一個 Composited Layer。

          有一些不能被壓縮的情況,可以在 無線性能優(yōu)化:Composite —— 層壓縮 中查看。

          參考資料

          1. 無線性能優(yōu)化:Composite —— 從-PaintLayers-到-GraphicsLayers
          2. Webkit 渲染基礎與硬件加速
          3. Chromium網頁Graphics Layer Tree創(chuàng)建過程分析
          4. Chrome中的硬件加速合成
          5. 瀏覽器渲染流程 詳細分析
          6. WebKit 渲染流程基礎及分層加速

          1. JavaScript 重溫系列(22篇全)
          2. ECMAScript 重溫系列(10篇全)
          3. JavaScript設計模式 重溫系列(9篇全)
          4.?正則 / 框架 / 算法等 重溫系列(16篇全)
          5.?Webpack4 入門(上)||?Webpack4 入門(下)
          6.?MobX 入門(上)?||??MobX 入門(下)
          7. 120+篇原創(chuàng)系列匯總

          回復“加群”與大佬們一起交流學習~

          點擊“閱讀原文”查看 120+ 篇原創(chuàng)文章

          瀏覽 65
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  黄色精品在线观看 | 好吊操在线观看 | 国产ss视频在线观看 | 噜噜噜噜影院 | 久久人人妻人人人人妻性色aV |