性能優化的根本目的:
要思考的是用戶使用網站的體驗如何,而不是我們可以節省多少字節,只有准確感知用戶的感受,我們才有必要談毫秒、字節和請求數量等問題。
針對優化注意事項:
- 防止過早優化:沒必要在剛開始階段就對一個細節進行放大型的優化,因為這樣的成本很高,除了代碼可讀性方面的東西,甚至還可能會引入更多的bug,所以,針對這個問題,我們可以在上線和運營的時候進行監控,當快暴露到問題的時候,進行整體優化。
- 本末倒置的關注:網站內容是最重要的,應該查看頁面的每個部分,看是否滿足網站頁面的主要目的,暫時不需要將額外的注意力全部放到一些不關乎本質的東西上。
對於性能的分析:
- 使用瀏覽器的性能分析工具,得到性能分析圖表,最著名的就是反向火焰圖表,針對瀏覽器的加載和渲染一目了然。
- 投入使用之前缺乏壓力測試和性能測試
性能優化(從用戶輸入網址到客戶端展現,一步一步優化)
1. 輸入網址 ==> 告訴瀏覽器你要去哪里
2. 瀏覽器查找DNS ==> 網絡世界是IP地址的世界,DNS就是ip地址的別名。從本地DNS到最頂級DNS一步一步的網上爬,直到命中需要訪問的IP地址
a. DNS預解析 使用CDN緩存,加快解析CDN尋找到目標地址(dns-prefetch)
3. 客戶端和服務器建立連接 ==>建立TCP的安全通道,3次握手
a. CDN加速 使用內容分發網絡,讓用戶更快的獲取到所要內容
b. 啟用壓縮 在http協議中,使用類似Gzip壓縮的方案(對服務器資源不足的時候進行權衡)
c. 使用HTTP/2協議 http2.0針對1.0優化了很多東西,包括異步連接復用,頭壓縮等等,使傳輸更快
4. 瀏覽器發送http請求 ==> 默認長連接(復用一個tcp通道,短連接:每次連接完就銷毀)
a. 減少http請求 每個請求從創建到銷毀都會消耗很多資源和時間,減少請求就可以相對來說更快展示內容
1). 壓縮合並js文件以及css文件
2). 針對圖片,可將圖片進行合並然后下載,通過css Sprites切割展示(控制大小,太大的話反而適得其反)
b. 使用http緩存 緩存原則:越多越好,越久越好。讓客戶端發送更少請求,直接從本地獲取,加快性能。
c. 減少cookie請求 針對非必要數據(靜態資源)請求,進行跨域隔離,減少傳輸內容大小。
d. 預加載請求 針對一些業務中場景可預加載的內容,提前加載,在之后的用戶操作中更少的請求,更快的響應
e. 選擇get和post 在http定義的時候,get本質上就是獲取數據,post是發送數據的。get可以在一個TCP報文完成請求,但是post先發header,再發送數據。so,考慮好請求選型。
f. 緩存方案選型 遞進式緩存更新(防止一次性丟失大量緩存,導致負載驟多)
5. 服務器響應請求 ==> tomcat、IIS等服務器通過本地映射文件關系找到地址或者通過數據庫查找到數據,處理完成返回給瀏覽器
a. 后端框架選型 \
==> 更快的響應,前端更快的操作。
b. 數據庫選型和優化 /
6. 瀏覽器接受響應 ==> 瀏覽器根據報文頭里面的數據進行不同的響應處理
a. 解耦第三方依賴 越多的第三方的不確定因素,會導致web的不穩定性和不確定性
b. 避免404資源 請求資源不到浪費了從請求到接受的所有資源
7. 瀏覽器渲染順序 ==> a.HTML解析開始構建dom樹
b. 外部腳本和樣式表加載完畢
a). 盡快加載css,首先將CSSOM對象渲染出來,然后進行頁面渲染,否則導致頁面閃屏,用戶體驗差
b). css選擇器是從右往左解析的,so類似#test a {color: #444},css解析器會查找所有a標簽的祖先節點,所以效率不是那么高
c). 在css的媒介查詢中,最好不要直接和任何css規則直接相關。最好寫到link標簽中,告訴瀏覽器,只有在這個媒介下,加載指定這個css
c. 腳本在文檔內解析並執行
a). 按需加載腳本,例如現在的webpack就可以打包和按需加載js腳本
b). 將腳本標記為異步,不阻塞頁面渲染,獲得最佳啟動,保證無關主要的腳本不會阻塞頁
c). 慎重選型框架和類庫,避免只是用類庫和框架的一個功能或者函數,而引用整個文件。
d. HTML DOM完全構造起來
a). DOM 的多個讀操作(或多個寫操作),應該放在一起。原則:統一讀、統一寫。
e. 圖片和外部內容加載
a). 對多媒體內容進行適當優化,包括恰當使用文件格式,文件處理、漸進式渲染等
b). 避免空的src,空的src仍然會發送請求到服務器
c). 避免在html內容中縮放圖片,如果你需要使用小圖,則直接使用小圖
f. 網頁完成加載
a). 服務端渲染,特別針對首屏加載很重要的網站,可以考慮這個方案。后端渲染結束,前端接管展示。
a) 針對首屏展示優化
1). 圖片懶加載 針對展示只加載第一屏,等用戶進行滾動的時候再進行加載。如果用戶對下面內容不感興趣,那么節省的請求。
2). 瀏覽器本地緩存模塊 可以通過按模塊去划分,將頁面的模塊緩存到localStory中,每次請求核對模塊版本號,丟失或者版本不一致重新請求,否則直接從本地拿(參考京東)
b) javascript優化
1). 減少對dom節點的查詢,因為每次都會重新去索引這個集合或者元素。或者查詢一次緩存起來,以待接下來使用
2). 進行js操作DOM的時候,考慮清楚頁面的重繪和重排,因為這些操作相對來說十分損耗性能的。
3). 避免使用eval和Function構造,因為解析器會將這些內容先轉換成可執行代碼,然后再進行接下去的操作。
4). 減少作用域鏈的查找,如果一個閉包函數使用到全局作用域的數據,那么每次局部作用域都會一層一層爬到最高作用域取得數據。
5). 數據訪問,對非引用類型數據訪問和局部變量的訪問是最快的。所以如果對引用類型的成員(對象的屬性或者數組的成員)訪問超過一次,則緩存
6). 將前端可能會使用的一些算法函數寫的更優化,在時間和空間復雜度上尋找到一個最優方案。
7). 去除重復加載同一模塊腳本
8). 智能事件處理,比如在一個div下有10個按鈕,可以在冒泡過程中捕獲這個事件源,然后注冊
c) css優化
1). 刪除無用規則
2). 內聯關鍵CSS
3). 避免@imports和Base64
4). 啟用高性價比屬性(如opacity over rgba())
5). 避免重復性工作
6). 不要一條條地改變樣式,而要通過改變class,或者csstext屬性,一次性地改變樣式。
7). 可將元素設為display: none(需要1次重排和重繪),然后N次操作,最后恢復顯示
8). position屬性為absolute或fixed的元素,重排的開銷會比較小,因為不用考慮它對其他元素的影響。
d) 圖片優化(網絡請求中80%都是靜態資源的請求)
1). 圖片正確格式的選擇
2). 圖片尺寸的選擇,在低分辨率等狀況下考慮降級處理(考慮響應式圖片)
3). 使用正確的工具進行優化(有損壓縮、無損壓縮)
4). 能用css處理和代理的,優先考慮css實現(陰影,濾鏡等)
5). 正確使用data url,比如說多地使用的地方,不建議data url,可考慮緩存
6). 考慮圖片的懶加載和元素可見加載方案
7). 圖片的預加載,在正確的合理的設計節點進行圖片的預加載
所有性能優化總結為三個層面優化:物理層面的優化,設計層面的優化,代碼層面的優化
注:設計層優化最主要的核心:衡量如何花費最少代價實現頁面功能
注:HTTP/2(超文本傳輸協議第2版,最初命名為HTTP 2.0),是HTTP協議的的第二個主要版本,HTTP/2的目標包括異步連接復用,頭壓縮和請求反饋管線化並保留與HTTP 1.1的完全語義兼容。Google Chrome、Mozilla Firefox、Microsoft Edge和Opera已支持HTTP/2,並默認啟用。Internet Explorer自IE 11開始支持HTTP/2,但僅限於Windows 10 Beta,並默認情況激活。
github地址:https://github.com/GerryIsWarrior/optimization 鄙人厚顏無恥要顆星,這樣才有動力持續更新
問題補充路徑:
1. 博客留言
2. gerry.zhong@outlook.com
3.github留言