客戶端優化
靜態資源優化
-
使用構建工具對HTML,CSS,JS壓縮,刪除生產環境下的無用代碼(比如註釋,打印信息等)。
-
提取公共資源,減少代碼體積。
-
外鏈CSS和JS文件,外鏈的文件可以放到CDN,服務器和瀏覽器會進行緩存。
-
使用雪碧圖,減少http請求數。
自動生成雪碧圖:www.toptal.com/developers/…
-
使用字體圖標iconfont:
-
圖片使用webp格式
-
緩存(Service Worker)
網絡請求優化:
-
使用get進行請求,get會緩存請求,比起post,只發送一個tcp包,效率更好。
-
合併請求數量,減少http請求次數,節省網絡請求時間。
接口合併(一個頁面需要多個並行或串行的接口實屬正常,網絡不好的情況下,最好的辦法就是通過接口合併的方式提高接口訪問速度)。
- 多次請求和關閉會造成服務了壓力,瀏覽器對每次請求的數量都有限制,一般是每次只能3次左右,合併請求將加快速度。
瀏覽器支持http並行請求數量有限,所以合併資源文件,可以加快請求,減少延遲 下載一個100kb的js文件比下載4個25kb的js更快。
- 拋開無用cookie,減少帶寬佔用,http協議每次發送請求都會自動帶上該域名及父級域名下的cookie
瀏覽器緩存
強緩存,協商緩存(根據相應的header內容來決定的)
瀏覽器在請求某一資源時,會先獲取該資源緩存的header信息,判斷是否命中強緩存(cache-control和expires信息)
若命中直接從緩存中獲取資源信息,包括緩存header信息;本次請求根本就不會與服務器進行通信
如果沒有命中強緩存,瀏覽器會發送請求到服務器,請求會攜帶第一次請求返回的有關緩存的header字段信息(Lase-Modified/If-Modified-Since和Etag/If-Node-Match),由 服務器根據請求中的相關header信息來比對結果是否協商緩存命中;
若命中,則服務器返回新的響應header信息更新緩存中的對應header信息,但是並不返回資源內容,它會告知瀏覽器可以直接從緩存獲取,否則返回最新的資源內容。
緩存參考文章
頁面渲染速度優化(用戶體驗優化)
- css放在頂部,優先渲染。
- js放在底部,避免堵塞,減少白屏時間和首頁渲染時間。
- 減少DOM數量,減少重排重繪。
- Virtual Dom。
- 預加載和懶加載。
- 骨架屏。
避免JS堵塞
使用async和defer,async不支持ie9,所以首推薦使用defer,如果使用defer或async請將script標籤放到head標籤中,以便讓瀏覽器更早地發現資源並在後臺線程中解析並加載JS
重排重繪
-
重排(reflow):渲染層內的元素佈局發生修改,都會導致頁面重新排列,比如窗口的尺寸發生變化,刪除或添加DOM元素,修改了影響元素盒子大小的css屬性(width,height,padding)
-
重繪(repain):所以對元素的視覺表現屬性的修改,都會引發重繪
不管是重排還是重繪,都會堵塞瀏覽器。要提高網頁性能,就要降低重排和重繪的頻率和成本,儘可能少的觸發重新渲染。
重排是CPU處理,重繪是GPU處理,CPU的處理效率遠不及GPU,並且重排一定會引發重繪,而重繪不一定會引發重排
避免重排重繪:
css複用class去批量操作元素樣式
圖片在渲染前指定大小:因爲img元素是內聯元素,所以在加載圖片後會改變寬高,嚴重的情況會導致整個頁面重排,所以最後砸渲染前就指定其大小,或者讓其脫離文檔流
Virtual Dom
Virtual Dom使用高效的diff算法,避免對整棵DOM樹進行變更,而是進行鍼對性的視圖變更,將效率做到最優化。
步驟:
1.生成Virtual Dom樹
2.對比兩顆樹的差異
比較兩顆DOM樹的差異是Virtual Dom算法最核心的部分,這也是我們常說的Virtual Dom的diff算法,但在比較的過程中,我們只比較同級的節點,非同級的節點不再我們的比較範圍內,這樣既可以滿足我們的需求,又可以簡化算法實現
比較樹的差異,首先是對樹進行遍歷,常用的又兩種遍歷算法,分別是深度優先遍歷和廣度優先遍歷,一般的diff算法中都採用的是深度優先遍歷。
對新舊兩顆樹進行一次深度優先的變量,這樣每個節點都會唯一的標記。在遍歷的時候,每遍歷到一個節點,就把該節點和新的樹的同一個位置的節點進行對比,如果有差異的話就記錄到一個對象裏面。
在差異對象中記錄了有改變的節點,每一個發生改變的內容也不盡相同,但也是有跡可循,常見的差異包括四種,分別是: 替換節點
增加/刪除子節點
修改節點屬性
改變文本內容
所以在記錄差異的時候要根據不同的差異類型,記錄不同的內容。
3.更新視圖
在第二步得到整顆樹的差異之後,就可以根據這些差異的不同類型,對DOM進行鍼對性的更新。與四中差異類型相對應的,是更新視圖時具體的更新方法,分別是:
replaceChild()
appendChild()/removeChild()
setAttribute()/removeAttribute()
textContent
服務器優化
- 使用內容分發網絡CDN 客戶端可以通過最佳的網絡鏈路加載靜態資源。
- 開啓Gzip壓縮文件內容。
- 爲文件頭指定expires和cache-control。
- 對於靜態內容,設置文件頭過期事件,expires的值爲永不過時(never expire)。
- 對於動態內容,使用恰當的cache-control文件頭來幫助瀏覽器進行有條件的請求。
- 升級到HTTPS,才能開啓http2和PWA功能。
Gzip壓縮
不要對圖片文件進行Gzip壓縮,對圖片進行壓縮不但會佔用後臺大量資源,壓縮效果其實並不可觀,可以 說"弊大於利",請在gzip_types把圖片相關項去掉。
CDN(內容分發網絡)
用戶和服務器之間距離越遠,經過的路由器越多,延遲也就越高。 CDN系統會遵循Cache-Control和Expires HTTP頭標準對改請求返回的內容進行緩存,便於後面的請求不再回源,起到加速功能。
HTTPS VS HTTP
我們對HTTP和HTTPS常規的理解就是,HTTPS比HTTP多了一層SSL(安全套接層),SSL需要對數據進行加密和解密,http使用tcp三次握手建立連接,客戶端和服務器端需要交換3個包。
https除了tcp三個包,還要加上ssl握手的9個包,所以一共是12個包。
所以http比https效率更高,https更安全
但是(此處是重點)
升級到https後,服務器可以開啓http2.0版本,對比http1.x性能和緩存各方面要更好,還有其他新特性, 可以啓動service work功能,更好的進行離線緩存,更好的離線體驗。
HTTPS證書可以免費申請,阿里雲跟騰訊雲都可以申請,按照文檔指示進行申請下載,然後將下載的證書上傳到服務器,配置服務器的內容,就可以開啓https、http2.0、service work等功能了。
HTTP2新特性
1.新的二進制格式
http1.x解析的是基於文本,基於文本協議的格式解析存在天然缺陷,文本的表現形式有多樣性, 要做到健壯性考慮的是場景必然很多,二進制則不同,只認0和1的組合。 基於這種考慮http2.0的協議解析決 定採用二進制合適,實現方便且健狀。
2.多路複用
即連接共享,每一個request都是用作連接共享機制的。 一個request對應一個id,這樣一個連接上可以有多個request, 每個連接的request可以隨機的混雜在一起,接收方可以根據request的id將request再歸屬到各自不同的服務器請求裏。
3.header壓縮
http1.x的header帶有大量信息,而且每次都要重複發送,http2.0使用encoder來減少需要傳輸的header大小,通訊雙方各自cache一份header fields表,即避免了重複header的傳輸,又減小了需要傳輸的大小。
4.服務器推送 server push
是http2協議裏面,唯一一個需要開發者自己配置的功能嗎,其他功能都是服務器和瀏覽器自動實現,不需要開發者擔心 概念:還沒有收到瀏覽器請求,服務器就把各種資源推送給瀏覽器 比如:瀏覽器只請求了index.html,但是服務器把index.html,style.css,example.png全部發送給瀏覽器。這樣的話,只需要一輪http通信,瀏覽器就得到了全部資源,提高了性能.
代碼優化
流程控制
-
避免使用for...in(它能枚舉到原型,所以很慢)
-
使用Map表代替大量的if-else和switch會提升性能和代碼可閱讀和維護性。
-
函數的防抖節流
-
事件委託的有點
1.減少內存消耗
有一個列表,列表之中有大量的列表項,我們需要在點擊列表項的時候相應一個事件:
如果給每個列表項一一都綁定一個函數,那對於內存消耗是非常大的,效率上需要消耗很多性能;
因此,比較好的方法就是把這個點擊事件綁定到他的父層,也就是ul上,然後再執行事件的時候再去匹配目標元素
所以事件委託可以減少大量的內存小號,節約效率
2.動態綁定事件
事件是綁定在父層的,和目標元素的增減是沒有關係的,執行到目標元素是在真正響應執行事件函數的過程中去匹配的
所以使用事件在動態綁定事件的情況下是可以減少很多重複工作的。
-
hidden
不管怎樣,你是否曾經爲了隱藏某個元素而使用過myElement.style.display = 'none‘這種方法呢?如果是的話,請別再這麼做了!只需要調用myElement.hidden = true即可實現元素隱藏的功能。
效率優化
-
易拓展,易維護,易維護的代碼(函數式編程),快速定位Bug。
flow靜態類型檢查,ESLint
模塊化變化才能,封裝共用的組件
-
引入Webpack,Rollup,Parcel等自動化構建工具
Webpack構建優化
區分開發環境和生產環境,自動提取公共代碼,壓縮代碼,開啓熱更新、自動保存刷新功能等。
使用ES6,引入babel-loader,並開啓緩存,解決兼容性。
引入Less,Sass等CSS預處理器,提高編碼效率和瀏覽器兼容性。
線上環境優化
錯誤監控
sentry(國外開源的錯誤監控,有線上環境也可以自行部署)
自動化構建、持續集成
Travis CI(對Github支持很友好)