前端性能優化-筆記

瀏覽器從輸入url到頁面呈現的過程作了哪些事情?

  1. 域名解析:解析輸入的域名查找對應的IP地址
1.1查找瀏覽器自身的DNS緩存
    1.2沒有找到條目,瀏覽器會搜索操做系統自身的DNS緩存
    1.3若是在DNS緩存也沒有找到,那麼嘗試讀取hosts文件
       (位於C:\Windows\System32\drivers\etc)
    1.4若是hosts文件也沒有找到,瀏覽器就會發起DNS解析請求,直到找到對應的IP地址
複製代碼
  1. TCP請求:
瀏覽器向web服務器發起TCP鏈接請求: 發起TCP的3次握手
複製代碼
  1. HTTP請求:
瀏覽器會經過TCP鏈接向遠程服務器發送HTTP請求
複製代碼
  1. 服務器端響應HTTP請求:
服務器端處理請求,返回html文件
複製代碼
  1. 瀏覽器解析html文件:
解析html文件,加載js,css,image等靜態資源
    向服務器端請求下載,會使用多線程去下載,不一樣瀏覽器之間線程數不同
    能夠用上keep-alive特性,創建一次HTTP鏈接,連續請求多個靜態資源
    好比: link標籤,發送請求獲取css
           script標籤,發送請求獲取js
           img標籤,發送請求獲取image圖片
複製代碼
  1. 瀏覽器根據html和css造成DOM樹和渲染樹,繪製到瀏覽器。
  2. 數據加載完成,斷開鏈接

資源合併與壓縮

  1. 合併:減小HTTP請求的數量javascript

  2. 壓縮:減小請求資源的大小css

    html壓縮:壓縮在文本文件中有意義,可是在html中不顯示的字符,包括空格,製表符,換行符等, 還有壓縮一些其餘意義的字符,如HTML註釋html

    方式: 
         1. 在線網站壓縮
         2. nodejs提供了html-minifier工具
    複製代碼

    css壓縮: 無效代碼刪除 css語義合併前端

    方式: 
         1. 使用clean-css對cssj進行壓縮
         2. 使用html-minifier對html中的css進行壓縮
    複製代碼

    js壓縮與混亂: 無效字符的剔除: 好比註釋回車空格,好比無效的變量 剔除註釋 代碼語義的縮減和優化: 好比變量名稱特別長sommmmesuisan, 壓縮爲s變量 代碼保護: 代碼的混亂對前端代碼的保護,將代碼的風格變的混亂下降可讀性vue

    方式: 
         1. 使用uglifyjs2對jsj進行壓縮
         2. 使用html-minifier對html中的js代碼進行壓縮
    複製代碼

    文件合併:java

    文件合併的帶來的問題:
         1. 首屏渲染問題: 首屏js文件加載過長,好比vue就會出現這樣的狀況
         2. 緩存失效問題: a17abdh12.js 和b128hsg12h.js兩個文件合併後,若是
             a17abdh12.js發生了變化,那麼這兩個文件合併後的js文件確定也會變化
             。致使用戶在訪問網站的時候以前緩存的js文件失效。
     
     真實場景:
         1. 通常公共庫會合併成一個文件,業務代碼會合併爲一個文件。公共庫修改
             很是少,而業務代碼變更的可能性很是高,因此業務代碼改動不會影響
             到公共庫代碼的緩存的失效。
     
     方式: 
         1. 利用nodejs實現文件合併,好比webpack來進行合併
    複製代碼

    開啓gzip:node

    服務端開啓gzip壓縮,縮小文件大小,瀏覽器獲取到gzip文件後在解壓縮
    複製代碼

圖片相關

png8/png24/png32之間的區別
    
    1. png8 --- 256色 + 支持透明  + 文件小不少
    2. png24 --- 2^24色 + 不支持透明 + 文件大不少
    3. png32 --- 2^24色 + 支持透明 + 文件最大
    
    備註:每種圖片格式都有本身的特色,針對不一樣的業務場景選擇不一樣的圖片格式很是重要
    
    不一樣格式圖片經常使用的業務場景: 
    
    1. jpg有損壓縮,文件體積小,不支持透明   ---大部分不須要使用透明圖片的場景
    2. png支持透明,瀏覽器兼容性好     --- 大部分須要使用透明圖片的場景
    3. webp壓縮體積最小,可是兼容性存在問題   --- ios支持存在問題,安卓嘗試使用
    4. svg矢量圖,代碼內嵌,相對較小,圖片樣式相對簡單的場景  --- 圖片樣式相對簡單的場景
    
複製代碼

圖片壓縮

  1. css雪碧圖,整合到一張圖片上,減小網站的HTTP請求數量。帶來的缺點: 整合圖片比較大的時候,一次加載就比較慢了。因此雪碧圖也要控制大小webpack

  2. Image inline,將圖片的內容內嵌到html當中,減小網站HTTP請求數量, 也就是base64格式的圖片,直接寫在html中,就不會發送HTTP請求了。ios

  3. 使用矢量圖, 使用SVG進行矢量圖的繪製,使用iconfont解決icon問題。web

  4. 在安卓下使用webp,圖片體積很是很是小,同時具備無損和有損壓縮。 在使用webp應該採用降級方式,若是支持使用webp,不然默認仍是使用jpg。

html頁面加載渲染的過程

瀏覽器解析html標籤渲染成DOM樹,當加載到link標籤,會併發的向服務器發送css的資源請求。 當加載到script標籤,會向服務器請求js資源,對css進行解析後結合DOM樹生成渲染樹,接着進行佈局,而後繪製。

html渲染過程的特色

  1. 順序執行, 併發加載

    • 詞法分析: 瀏覽器對html文檔解析的方式,從最開始的部分對標籤進行從上到下的解析,解析過程從上到下,順序執行!
    • 併發加載: html引入的外部資源是併發加載的
    • 併發上限: 某個域名下的請求數量是存在上限的,因此對某個域名下所請求資源的數量從而避免達到併發上限
  2. 是否阻塞

    • css阻塞
    1. head標籤中阻塞頁面渲染
            推薦使用link標籤的方式在head中在html中引入
        2. css不阻塞外部腳本js的併發加載,可是會阻塞外部腳本js的執行
            由於js在操做DOM的時候,有可能涉及到css樣式的修改,而這個css樣式的修改
            是基於以前css樣式的渲染。因此在css代碼渲染完畢,纔會進而執行js代碼,
            也就是css代碼阻塞了外部js的執行
    複製代碼
    • js阻塞
    1. 直接引入的js阻塞頁面的渲染,好比<script src='a.js'></script>
            js代碼中頗有可能去調用document.write方法來修改DOM文檔的結構,
            因此須要等待js代碼執行完畢,進而去繼續執行html標籤的分析,
            因此js腳本代碼中不要出現document.write這樣的代碼
        2. js不阻塞外部資源的加載
        3. js順序執行,會阻塞後續js邏輯的執行
            舉個例子:<script src='a.js'></script>
                      <script src='b.js'></script>
            按照這樣的順序引入,會在a.js裏面的代碼執行完畢接着執行b.js裏面的代碼
            由於js的執行是單線程的,也就是b.js裏面執行的代碼能夠依賴a.js中的代碼
        
    複製代碼
  3. 引入方式

  • js引入方式
1. 直接引入
    2. defer: 確保全部的DOM樹都生成
    3. async:不能確保腳本js文件之間的依賴關係,因此async引入的js腳本不能存在依賴關係
    4. 異步動態引入js: 在須要某個js文件的時候,經過生成script標籤來引入

複製代碼

css和js文件加載過程的優化點

  1. css樣式表存放在head中,確保css和html一塊兒生成渲染樹,而不至於從沒有樣式,跳轉到有樣式的狀況,出現頁面閃動。
  2. 用link標籤代替@import這樣引入css的方式,@import的方式沒法併發加載,另外@import這樣的方式會在DOM加載結束後纔會加載
  3. js腳本文件放在body底部
  4. 合理使用js的異步加載能力,就是採用動態生成script標籤,動態加載所須要的js文件

async 和 defer

  1. async 確保在全部html頁面dom渲染完以後纔會加載
  2. async 加載的js腳本文件,不是按照順序加載的,因此只有幾個js腳本沒有依賴關係,才能夠經過async的方式來加載腳本文件
  3. defer 不阻塞頁面渲染,是按照順序執行的,會按照script的順序依次執行。在DOM渲染完成以後纔會執行。

動態引入js腳本

function loadScript(src) {
        let ele = document.createElement('script');
        ele.type = 'text/javascript';
        ele.src = src
        document.body.appendChild(ele)
    }
    loadScript('demo.js')

複製代碼

懶加載和預加載

懶加載

  1. 圖片進入可視區域以後請求圖片資源
  2. 對於電商等圖片不少,頁面很長的業務場景很是適用
  3. 減小無效資源的加載,由於可能用戶只訪問100張圖片,剩下的100張是沒有必要加載出來,這些資源就是屬於無效資源。

預加載

  1. 圖片等靜態資源在使用以前提早請求圖片資源
  2. 資源在使用到的時候從緩存中加載,提高用戶體驗

重繪和迴流

迴流(reflow): 當render tree中的一部分由於元素尺寸,佈局,隱藏等改變而須要從新構建,稱爲迴流。 當頁面佈局和幾何屬性改變時就會迴流。

觸發迴流的屬性

  1. 盒子模型相關屬性
width, height, padding, margin,display,border-width, border,min-height
複製代碼
  1. 定位屬性
top, bottom, left, right, position, float, clear
複製代碼
  1. 改變節點內部文字結構像相關屬性
text-align, overflow-y, font-weight, overflow, font-family, line-height
    vertical-align, white-space, font-size
複製代碼

重繪:當render tree中一些元素須要更新屬性,而這些屬性只是影響元素顏色風格,而不影響佈局的,好比background-color,color等 稱爲重繪。

只會觸發重繪的屬性

color, border-style, border-radius, visibility, text-decoration, background,
    background-size, background-image,background-position, background-repeat,
    outline-color, outline, outline-style, box-shadow
複製代碼

重繪不必定會觸發迴流,可是迴流必定會繪製重繪

重繪迴流優化方式:

  1. 避免使用觸發重繪,迴流的CSS屬性
  2. 將重繪和迴流的範圍限制在單獨的圖層以內(暫時不理解.....)

實際工做中CSS關於迴流和重繪的總結

  1. translate 替換top的變化
    translate不會觸發迴流,top會觸發迴流

  2. opacity 替換visiblity
    visiblity只會觸發重繪的過程,opacity不會觸發重繪的過程

    // bad
        setTimeout(() => {
            document.getElementById('box').style.visiblity = 'hidden'
        }, 2000)
        
        // good
        #box {
            width: 100px;
            height: 100px;
            background: red;
            transform: translateZ(0);  // 在瀏覽器的層面創建一個新圖層
            opacity: 1;
        }
        setTimeout(() => {
            document.getElementById('box').style.opacity = 0
        })
    複製代碼
  3. 不要一條一條的地修改DOM的樣式,預先定義好class,而後修改DOM的ClassName

// bad
    var box = document.getElementId('box')
    setTimeout(() => {
        box.style.width = '200px';  
        box.style.height = '200px';
        box.style.background = 'red'
    })
    
    // good
    .box {
        width: 200px;
        height: 200px;
        background: red;
    }
    setTimeout(() => {
        box.classList.add('box');
    })
複製代碼
  1. 把DOM離線後修改(好比,須要頻繁操做DOM並將DOM的樣式進行修改,那麼能夠先將DOM的display:none(有一次迴流),而後你修改DOM樣式100次,在display:block顯示出來)
  2. 不要使用table佈局,可能很小的小改動會形成整個table的從新佈局
  3. 合理選擇動畫的速度
  4. 當使用實現動畫的時候,啓用GPU硬件渲染加速,固然若是數據量很大,須要從cpu到gpu的過程也是很是耗費時間的,這個也是須要考量的
.box {
        transform: translateZ(0);
        transform: translate3d(0,0,0);  // 啓用GPU硬件加速
    }
```

複製代碼
相關文章
相關標籤/搜索