1. 程式人生 > >奇舞-關鍵渲染路徑效能優化-筆記

奇舞-關鍵渲染路徑效能優化-筆記

內容

  • 瀏覽器渲染原理
  • 資源對渲染的影響
  • 優化關鍵渲染路徑

瀏覽器渲染原理

這裡寫圖片描述

DOM

這裡寫圖片描述

Timeline

這裡寫圖片描述

錄製時需注意

  • 禁用快取,以便測試首次瀏覽效能

這裡寫圖片描述

  • 關閉Chrome 擴充套件 或使用隱身模式
  • 模式真實網路情況
    這裡寫圖片描述

  • Chrome Canary

總結TImeline

1:控制條

  • 開始記錄, 停止記錄
  • 配置記錄期間捕獲的資訊

2: 總攬

  • 頁面效能高階彙總

3:火焰圖

  • CPU 堆疊追蹤的視覺化

4:詳情

  • 每個CPU 任務的詳細報告
    這裡寫圖片描述

增量構建

瀏覽器無需等待html 載入完畢,便可開始解析DOM

自己動手

使用 performance 工具 分析自己常逛的網站。找到主執行緒中構建DOM所在的步驟

總結

描述瀏覽器是如何構建DOM的

CSSOM

這裡寫圖片描述

這裡寫圖片描述

這裡寫圖片描述

RenderTree

  • RenderTree 包含了渲染網頁所需要的節點
  • 無需渲染的節點不會被新增到RenderTree中。
    思考Lvisitilty:hidden 的節點,是否會被新增到RenderTree?

Recalculate Style : 構建 RenderTree

這裡寫圖片描述

Layout :計算渲染書節點的位置和大小

Viewport

  • device-width 為瀏覽器的理想視口
  • 在移動端 ,如果不設定viewpost 寬度為理想視口,viewport寬度通常為,980px,這會導致文字很小,我們需要手動放大閱讀

思考 :

哪些操作會觸發Layout

總結

試著畫出瀏覽器渲染過程
並描述每一步執行的工作

構建DOM

  • 構建過程
    character token node DOM
  • 增量構建

構建CSSOM

  • 構建過程
    charactor token node CSSOM
  • 選擇器越複雜,匹配用的時間越多

構建RenderTree

  • RenderTree 包含所有需要呈現在頁面上的節點資訊
  • display:none 的元素不會被新增到RenderTree 彙總,因為不需要本渲染
  • visibility:hidden 的元素會被新增到RenderTree中,因為它雖然不可見,但是會佔有位子

Layout

  • 計算需要渲染的節點的大小和位置
  • 節點位置和大小是給予viewport計算的
  • 在移動端通常將viewport設為瀏覽器推薦的理想適口,以保證字型顯示大小易於閱讀
  • 旋轉螢幕,修改瀏覽器大小,修改位置大小相關的css屬性都有可能觸發Layout

Paint

  • 根基background,border, box-shadow等樣式,將Layout生成區域填充為最終將顯示在螢幕上的畫素

資源對渲染的影響

資源

  • css
  • js
  • font
  • img

思考

瀏覽器會在何時渲染頁面

  1. 載入完DOM立即開始渲染
  2. 載入完DOM和CSSOM

css阻塞初次渲染(有待測試)
‘index.css’>
- 通過以上兩種方式定義css,均會阻塞初次渲染
- 瀏覽器會在解析完css後,再進行渲染,這是為了防止樣式突變帶來餓抖動
- 不管css 出現文件中的那個位置,都會阻塞整個文件的初次渲染
- 通過link 標籤引入的css阻塞的時間可能更長,因為載入它需要一個網路來回時間

dedia query

<link rel='sty;esheet' href='index_print.css' media='print'> 
  • 此樣式表仍會載入
  • 當瀏覽器環境不匹配媒體查詢時,改樣式表不會阻塞渲染
  • 我們可針對不同媒體環境拆分css檔案,併為link標籤新增媒體查詢,避免為了載入非關鍵css資源,而阻塞初次渲染。

通過documnt.write 新增link


<script>
document.write('<link ref='stylesheet' href='inex.css' />')
</script>

通過DOM API 新增link
var style = document.createElement(‘link’)
style.rel = ‘stylesheet’;
style.href = ‘index.css’;
document.head.appendChild(style)
不會阻塞初次渲染

preload

<link / rel='preloa' href='index_print.css' as=style onloa='this.rel=stylesheet'>
  • fel 不是stylesheet,因此不會阻塞渲染
  • preloa 是resoure hint 規範中定義中一個功能
  • resource hint 通過告知瀏覽器提前 建立連結或載入資源,以提高資源載入的速度
  • 瀏覽器遇到標記為preloa的link 時,會開始載入它
  • 當onload 時間發生時,將rel改為stylesheet 即可應用此樣式

loadCSS.js

  • CSS preload polyfill
  • 讓我們可以使用preloa 語法非同步載入css
  • 原理是通過DOM API 插入樣式資源

這裡寫圖片描述

思考

<body>
<p>hello</p>
// 這個指令碼會載入10秒左右
<script src='slowscript.js'></script>
<p>world</p>
</body>
//顯示情況是 立即顯示hello 10秒後顯示world

javascript 阻塞HTML parser

// inline js
<script></script>
// external js
<script src='somescript'></script>
  • 通過以上兩種方式引入js指令碼均會阻塞html parser,因而會阻塞出現在指令碼後面的HTML 標記的渲染
  • 外部script 阻塞時間一般更長,以為可能包含了一個網路來回時間
  • javascript 可以通過document.write 修改HTML 文件流,因此在執行js時, 瀏覽器會暫停解析DOM的工作
<html>
 <head>
 //p {color: green}
 <link rel='stylesheet' href = 'index.css'>
 </head>
 <body>
   <p>hello wrold</p>
     <script>
       let p = document.querySelector('p');
       let color = window.getComputedStyle(p).color
       console.log(color)
     </script>
 </body>
</html>

//如果HTML Parse 解析到<script></script> 標籤時,樣式仍未載入完成,會發生什麼? 最後列印的顏色是多少?

CSS阻塞JS

//inline js
<script> //app logics here <script>

//external js

<script src='somescript.js'></script>
  • 通過以上兩種方式引入的JS均會被CSS 阻塞
  • 由於這些javascript 可能會讀取或修改CSSOM,因此需要等待CSSOM 構造完成後,它們才會執行
<html>
  <head>
   <script src='index.js'></script>
   <script> src='tongji.js' </script>
  </head>
  <body>
  </body>
</html>
//這兩個js檔案瀏覽器會同時載入

Preloa

  • 當HTML parse 被指令碼阻塞時,Parser 雖然停止構建DOM,但仍會識別該指令碼後面的資源,並提前載入。
  • 注意:這裡是指的瀏覽器資源載入策略,而非前文提到的resource hint 標準中的preload

使用defer延遲指令碼執行

<script src=='index.css' defer><script>
  • 當script 標籤擁有defer 屬性時,該指令碼會被退到整個HTML文件解析完成後,再開始執行。
  • 被defer 指令碼, 在執行時會嚴格按照HTML文件中出現的順序位置

延遲指令碼方法對比

使用的的方法,可提早指令碼資源載入

由於HTML Parser 是增量解析 HTML文件的,因此將指令碼放在head中,可以提早瀏覽器對指令碼檔案的載入。

使用async 非同步載入指令碼

  • 當script 標籤擁有async 屬性時,該指令碼不會再阻塞html parser 且不會被css 阻塞
  • 指令碼只要載入完成,便可開始執行
  • 被async 的指令碼,在執行時會 不會按照在html文件中出現的順序文件執行
  • async 適用於無依賴的獨立資源

這裡寫圖片描述

這裡寫圖片描述

<link href='https://fints.googleapis.com/css...'>
<style type='text/css' media='screen. print'>
  h1 {
      font-family:'Roboto'
  }
//載入完HTML 文件後, 瀏覽器會如何工作?
// 等字型檔案載入完成後顯示內容
</style>

font 阻塞內容渲染

  • 瀏覽器為了避免FOUT(Flash Of Unstyled Text) 會盡量等字型載入完成後, 再顯示應用了該字型的內容
  • 只有當字型超過一段時間仍未載入成功時, 瀏覽器才會降級使用系統字型,每個瀏覽器都規定了自己的超時時間
  • 但這也帶來了FOIT(falst Of invisible Text) 問題, 內容無法儘快被展示,導致空白。

非同步載入字型

通過非同步載入css 。即可避免字型阻塞渲染

<body>
  <img src='smile.png'>
  <p>hello world</p>
</body>

//圖片資源是否會阻塞首次渲染  答案是不會

優化關鍵渲染路徑

優化目標

將一下指標壓縮到最低

  • 關鍵資源數
  • 關鍵資源體積
  • 關鍵資源網路來回數

這裡寫圖片描述

這裡寫圖片描述

勿盲目內聯資源

  • 若啟用HTTP2 ,則無需內聯資源
  • 若資源被多個頁面共享,則無法充分利用快取, 導致重複下載

結合內聯與快取

<html>
   <head>
    <style></style>
     <link rel='prefetch' href = 'index.css'></link>
   </head>

    <body>
      <p> hello world</p>
    </body>
</html>
  • 當用戶首次訪問時,返回內聯資源,並通過prefetch,請求並快取資源;
  • 在使用者首次訪問時, 通過cookie 表示使用者已載入快取
  • 當下次訪問時, 若cookie 標示已經快取過,則只返回外部資源標記
  • 快取策略可靈活選擇

減少內容大小

  • 避免返回無用內容
  • 針對特定語言的原始碼壓縮
  • 通過文字壓縮
  • 圖片壓縮

這裡寫圖片描述

關鍵呈現路徑優化思路

  • 延遲或非同步載入資源, 從而減少關鍵資源數量
  • 減少資源大小
  • 針對關鍵資源, 減少網路請求時間

學習資源

  • 關鍵資源呈現路徑, by Chrome Developer
  • 使用Chrome Devtool 檢查效能
  • 效能優化相關資源彙總