前端效能最佳化百問大雜燴

肥晨發表於2023-02-14

主要內容為下面幾大類:移動端、圖片、JavaScript、css、html、頁面內容、伺服器、cookie。

移動端效能最佳化:

  1. 保持單個檔案小於25KB
    移動網站頁面要求下載資源,如果檔案過大,會大大減慢頁面載入速度。

  2. 打包內容為分段multipart文件
    由於HTTP請求每一次都會執行三次握手,每次握手都會消耗較多的時間。使用multipart,實現了多檔案同時上傳,可用一個HTTP請求獲取多個元件。

圖片最佳化:

  1. CSS sprites
    俗稱 CSS 精靈、雪碧圖,雪花圖等。即將多張小圖片合併成一張圖片,達到減少 HTTP 請求的一種解決方案。可透過 CSS中的background 屬性訪問圖片內容。這種方案同時還可以減少圖片總位元組數,節省命名詞彙量。

  2. 壓縮圖片
    圖片佔據資源極大,因此儘量避免使用多餘的圖片,使用時選擇最合適的格式大小,然後使用智圖壓縮,同時在程式碼中用Srcset來按需顯示。(切記不要過分壓縮 可能會導致圖片迷糊)

  3. 儘量避免重設圖片大小
    重設圖片大小是指在頁面、CSS、JavaScript等中多次重置圖片大小,多次重設圖片大小會引發圖片的多次重繪,影響效能。

  4. 圖片儘量避免使用DataURL
    DataURL圖片沒有使用圖片的壓縮演算法檔案會變大,並且要解碼後再渲染,載入慢耗時長。

  5. 圖片懶載入
    圖片對頁面載入速度影響非常大。比如,當一個頁面內容比較多的時候,載入速度就會大大的降低,極大的影響到使用者體驗 。更有甚者,一個頁面可能會有幾百個圖片,但是頁面上僅僅只顯示前幾張圖片,那其他的圖片是否可以晚點載入用於提高效能。具體可見 >>

JavaScript相關最佳化

  1. 把指令碼放在頁面底部
    放在前面js載入會造成阻塞,影響後面dom的載入

  2. 使用外部JavaScript和CSS
    在現實環境中使用外部檔案通常會產生較快的頁面,因為 JavaScript 和 CSS 有機會被瀏覽器快取起來。對於內聯的情況,由於 HTML 文件通常不會被配置為可以進行快取的,所以每次請求 HTML 文件都要下載 JavaScript 和 CSS。所以,如果 JavaScript 和 CSS 在外部檔案中,瀏覽器可以快取它們,HTML 文件的大小會被減少而不必增加 HTTP 請求數量。

  3. 壓縮JavaScript和CSS
    壓縮檔案是為了降低網路傳輸量,減少頁面請求的響應時間。

  4. 減少DOM操作
    操作dom會產生幾種動作,極大的影響渲染的效率。其中layout(佈局)和paint(繪製)是最大的。

  5. js開銷縮短解析時間
    開銷:載入-》解析和編譯-》執行
    js的解析和編譯,執行要花很長時間(谷歌開發工具中的performance中可以檢視。選中main主執行緒中的某一段。)
    解決方案:

    • 程式碼拆分按需載入
    • tree shaking程式碼減重
    • 避免長任務
    • requestAnimationFrame和repuestIdleCallback進行時間排程
  6. v8編譯原理(程式碼最佳化)

    • 解析js程式碼成抽象語法樹-》位元組碼-》機器碼
      編譯過程會進行最佳化
      執行時可能會發生反最佳化
    • v8內部最佳化
      指令碼流:邊下載邊解析
      位元組碼快取:常用的位元組碼會存起來(這個檔案用到其他的檔案也用到的引數)
      函式懶解析:先解析用到的
    • 物件最佳化(迎合v8進行最佳化)
      保證物件初始化順序一致(物件初始化時v8會生成隱藏屬性以便後續複用並且是按照順序排序的)
      不要直接賦值物件新屬性(追加的屬性需要透過描述陣列間接查詢)
      使用陣列代替類陣列(v8會對陣列進行最佳化)比如先將類陣列轉化成陣列
      避免讀取陣列越界(比如for迴圈多查詢1個下標會照成效能相差6倍)

造成undefined和數字比較
陣列也是物件,當找不到對應下標的時候回沿著原型鏈向上找造成額外開銷
業務上無效

  1. js記憶體,避免造成記憶體洩漏
    透過變數是否能被訪問到來判斷記憶體是否釋放。
  • 區域性變數: 函式執行完沒有閉包引用會被標記回收
  • 全域性變數: 直到瀏覽器被解除安裝頁面釋放
  • 回收機制:
    引用計數:每呼叫一次加一,當計數為0的時候進行回收。缺點是不能解決迴圈引用(例如a物件依賴於b物件,標記清除(垃圾回收): 從根節點去訪問,當訪問到不能被訪問的物件就進行標記然後進行垃圾回收。(當a物件
    解決:避免意外的全域性變數;避免反覆執行引發的閉包;避免脫離的dom元素沒有被回收(所以react有ref這個api)。

CSS 相關最佳化

  1. 把樣式表放在標籤中
    css放在head標籤中比css放在body標籤尾部少了一次構建RenderTree, 一次計算佈局和一次渲染網頁, 因此效能會更好。
  2. 不要使用CSS樣式表
  3. 使用替代@import
  4. 不要使用filter
  5. 避免元素型別轉化(陣列中放多種型別不利於v8引擎最佳化程式碼)
    • 降低css對渲染的阻塞(按需載入,放在dom前面載入)
    • 利用pu完成動畫(前面講到的複合)
    • 使用contain進行最佳化(最佳化強度大。例如: contan:layout告訴瀏覽器這個節點內部的子元素和外面的使用font-display進行最佳化:讓文字更早的顯示在頁面上,減輕文字閃動的問題

html 相關最佳化

  1. 減少iframes使用
  2. 壓縮空白符
  3. 避免巢狀層次太深
  4. 避免使用table佈局
  5. 減少沒必要的註釋
  6. 刪除元素預設屬性(比如預設checkbox等)

開發內容相關最佳化

  1. 減少HTTP請求數
  2. 減少DNS重定向
  3. 快取AJax請求
  4. 延遲載入
  5. 預載入
  6. 減少DOM元素的數量
  7. 劃分內容到不同域名
  8. 儘量減少使用iframe
  9. 避免404錯誤

伺服器相關最佳化

  1. 使用CDN
  2. 新增Expires或Cache-Control響應頭
  3. 啟用Gzip
  4. 配置Etag
  5. 儘早輸出緩衝
  6. Ajax請求使用GET方法
  7. 避免圖片src為空
  8. 傳輸載入最佳化
    伺服器啟用gzip
  9. keep Alive(持久TCP連線)
    keepalive_requests 100;請求100次後開啟http的keepAlive有keepalive_timeout 65;65秒後關閉。
  10. http快取
    最好是用no-cache(要用的時候需要在伺服器那邊Etag驗證下)
  11. service workers
    • 加速重複訪問
    • 離線支援

Cookie相關最佳化

  1. 減少cookie大小
  2. 靜態資源使用無cookie域名

首屏載入最佳化

  1. 資源壓縮、傳輸壓縮、程式碼拆分、tree shaking、http快取
  2. 路由懶載入、預渲染、inlineCss、虛擬列表
  3. prefetch和preload調整載入順序js記憶體管理

相關文章