淺析如何更好的進行效能優化:構建策略、影象策略、分發策略、快取策略、CSS策略、DOM策略、阻塞策略、迴流策略、非同步更新策略
主要來源於這篇文章:寫給中高階前端關於效能優化的9大策略和6大指標 | 網易四年實踐,算是這篇文章的學習筆記。
效能優化:從過程趨勢來說,可分為網路層面和渲染層面;從結果趨勢來說,可分為時間層面和體積層面。
一、網路層面
網路層面的優化就是讓資源體積更小,載入更快。
1、構建策略 —— webpack
減少打包時間:縮減範圍、快取副本、定向搜尋、提前構建、並行構建、可視結構
減少打包體積:分隔程式碼、搖樹優化、動態墊片、按需載入、作用提升、壓縮資源
(1)縮減範圍:配置 include/exclude 縮小 loader 對檔案的搜尋範圍。好處是避免不要的轉義,node_modules 目錄體積這麼大,那得增加很長時間去檢索檔案。
(2)快取副本:配置cache快取Loader對檔案的編譯副本,好處是再次編譯時只編譯修改過的檔案,未修改過的檔案就不需要要隨著修改過的檔案重新編譯了。
(3)定向搜尋:配置resolve提高檔案的搜尋速度,好處是定向指定必須檔案路徑。若某些第三方庫以常規形式引入可能報錯或希望程式自動索引特定型別檔案都可通過該方式解決。
alias
對映模組路徑,extensions
表明檔案字尾,noParse
過濾無依賴檔案。通常配置alias
和extensions
就足夠。
export default {
// ...
resolve: {
alias: {
"#": AbsPath(""), // 根目錄快捷方式
"@": AbsPath("src"), // src目錄快捷方式
swiper: "swiper/js/swiper.min.js"
}, // 模組匯入快捷方式
extensions: [".js", ".ts", ".jsx", ".tsx", ".json", ".vue"] // import路徑時檔案可省略字尾名
}
};
(4)提前構建:配置DllPlugin將第三方依賴提前打包,好處是將DLL與業務程式碼完全分離,且每次只構建業務程式碼。 —— webpack v4+ 已不需要推薦使用該配置。
(5)並行構建:配置Thread將Loader單程序轉換為多程序,好處是釋放 CPU 多核併發的優勢。
(6)可視結構:配置BundleAnalyzer分析打包檔案結構,好處是找出體積過大的原因,從而通過分析原因得出優化方案減少構建時間。
(7)分割程式碼:分割各個模組程式碼,提取相同部分程式碼,好處是減少重複程式碼的出現頻率。webpack v4
使用 splitChunks
替代 CommonsChunksPlugin
實現程式碼分割。
(8)搖樹優化:刪除專案中未被引用程式碼,好處是移除重複程式碼和未使用的程式碼。搖樹優化首次出現於
rollup
,是rollup
的核心概念,後來在webpack v2
裡借鑑過來使用。在 webpack
裡只需將打包環境設定成生產環境
就能讓搖樹優化
生效,同時業務程式碼使用ESM規範
編寫,使用import
匯入模組,使用export
匯出模組。
export default {
// ...
mode: "production"
};
(9)動態墊片:通過墊片服務根據UA返回當前瀏覽器程式碼墊片,好處是無需將繁重的程式碼墊片打包進去。每次構建都配置@babel/preset-env
和core-js
根據某些需求將Polyfill
打包進來,這無疑又增加了程式碼體積。@babel/preset-env
提供的useBuiltIns
可按需匯入Polyfill
。
在此推薦大家使用動態墊片
。動態墊片
可根據瀏覽器UserAgent
返回當前瀏覽器Polyfill
,其思路是根據瀏覽器的UserAgent
從browserlist
查找出當前瀏覽器哪些特性缺乏支援從而返回這些特性的Polyfill
。
使用html-webpack-tags-plugin在打包時自動插入動態墊片
。
import HtmlTagsPlugin from "html-webpack-tags-plugin";
export default {
plugins: [
new HtmlTagsPlugin({
append: false, // 在生成資源後插入
publicPath: false, // 使用公共路徑
tags: ["https://polyfill.alicdn.com/polyfill.min.js"] // 資源路徑
})
]
};
(10)按需載入:將路由頁面/觸發性功能單獨打包為一個檔案,使用時才載入,好處是減輕首屏渲染的負擔。(這個應用就很常見了)
(11)作用提升:分析模組間依賴關係,把打包好的模組合併到一個函式中,好處是減少函式宣告和記憶體花銷。作用提升首次出現於
rollup
,是rollup
的核心概念,後來在webpack v3
裡借鑑過來使用。
在未開啟作用提升
前,構建後的程式碼會存在大量函式閉包。由於模組依賴,通過webpack
打包後會轉換成IIFE
,大量函式閉包包裹程式碼會導致打包體積增大(模組越多越明顯
)。在執行程式碼時建立的函式作用域變多,從而導致更大的記憶體開銷。
在開啟作用提升
後,構建後的程式碼會按照引入順序放到一個函式作用域裡,通過適當重新命名某些變數以防止變數名衝突,從而減少函式宣告和記憶體花銷。
在webpack
裡只需將打包環境設定成生產環境
就能讓作用提升
生效,或顯式設定concatenateModules
。
export default {
// ...
mode: "production"
};
// 顯式設定
export default {
// ...
optimization: {
// ...
concatenateModules: true
}
};
(12)壓縮資源:壓縮HTML/CSS/JS程式碼,壓縮字型/影象/音訊/視訊,好處是更有效減少體積。極致地優化程式碼都有可能不及優化一個資原始檔的體積更有效。
2、影象策略 —— 主要圍繞影象型別
做相關處理,同時也是接入成本較低的效能優化策略
。
只需做到以下兩點即可。
- 影象選型:瞭解所有影象型別的特點及其何種應用場景最合適
- 影象壓縮:在部署到生產環境前使用工具或指令碼對其壓縮處理
影象選型
一定要知道每種影象型別的體積/質量/相容/請求/壓縮/透明/場景
等引數相對值,這樣才能迅速做出判斷在何種場景使用何種型別的影象。
影象策略
也許處理一張影象就能完爆所有構建策略
,因此是一種很廉價但極有效的效能優化策略
。
3、分發策略 —— 主要圍繞內容分發網路
做相關處理,同時也是接入成本較高的效能優化策略
,需足夠資金支援。
CDN
最大作用。
- 所有靜態資源走CDN:開發階段確定哪些檔案屬於靜態資源
- 把靜態資源與主頁面置於不同域名下:避免請求帶上
Cookie
瀏覽器快取
做相關處理,同時也使接入成本最低的效能優化策略
。能顯著減少網路傳輸所帶來的損耗,提升網頁訪問速度,是一種很值得使用的效能優化策略
。
有兩種較常用的應用場景值得使用快取策略
一試,當然更多應用場景都可根據專案需求制定。
- 頻繁變動資源:設定
Cache-Control:no-cache
,使瀏覽器每次都發送請求到伺服器,配合Last-Modified/ETag
驗證資源是否有效 - 不常變化資源:設定
Cache-Control:max-age=31536000
,對檔名雜湊處理,當代碼修改後生成新的檔名,當HTML檔案引入檔名發生改變才會下載最新檔案
二、渲染層面
渲染層面的效能優化,無疑是如何讓程式碼解析更好執行更快。這種是在開發程式碼層面需要考慮的,其實蠻多,我之前也總結過,這裡作者寫的也挺好。
1、CSS策略
(1)避免出現超過三層的巢狀規則
(2)避免為ID選擇器
新增多餘選擇器
(3)避免使用標籤選擇器
代替類選擇器
(4)避免使用通配選擇器
,只對目標節點宣告規則
(5)避免重複匹配重複定義,關注可繼承屬性
2、DOM策略
(1)快取DOM計算屬性
(2)避免過多DOM操作
(3)使用DOMFragment
快取批量化DOM操作
3、阻塞策略
(1)指令碼與DOM/其它指令碼
的依賴關係很強:對<script>
設定defer
(2)指令碼與DOM/其它指令碼
的依賴關係不強:對<script>
設定async
4、迴流重繪策略
(1)快取DOM計算屬性
(2)使用類合併樣式,避免逐條改變樣式
(3)使用display
控制DOM顯隱
,將DOM離線化
5、非同步更新策略
(1)在非同步任務
中修改DOM
時把其包裝成微任務
三、優化指標
- 載入優化:資源在載入時可做的效能優化
- 執行優化:資源在執行時可做的效能優化
- 渲染優化:資源在渲染時可做的效能優化
- 樣式優化:樣式在編碼時可做的效能優化
- 指令碼優化:指令碼在編碼時可做的效能優化
- V8引擎優化:針對
V8引擎
特徵可做的效能優化
以上內容大多都有用到,具體內容可看作者文章詳情。
以上作者所寫內容大多都有用到,但是構建策略webpack裡的12個內容,我確實用的不多,所以記錄一下,準備找機會把 webpack 系統的研究一下。