大前端性能優化總結

客戶端優化

靜態資源優化

網絡請求優化:

  • 使用get進行請求,get會緩存請求,比起post,只發送一個tcp包,效率更好。

  • 合併請求數量,減少http請求次數,節省網絡請求時間。

接口合併(一個頁面需要多個並行或串行的接口實屬正常,網絡不好的情況下,最好的辦法就是通過接口合併的方式提高接口訪問速度)。

  • 多次請求和關閉會造成服務了壓力,瀏覽器對每次請求的數量都有限制,一般是每次只能3次左右,合併請求將加快速度。

瀏覽器支持http並行請求數量有限,所以合併資源文件,可以加快請求,減少延遲 下載一個100kb的js文件比下載4個25kb的js更快。

  • 拋開無用cookie,減少帶寬佔用,http協議每次發送請求都會自動帶上該域名及父級域名下的cookie

瀏覽器緩存

強緩存,協商緩存(根據相應的header內容來決定的)

瀏覽器在請求某一資源時,會先獲取該資源緩存的header信息,判斷是否命中強緩存(cache-controlexpires信息)

若命中直接從緩存中獲取資源信息,包括緩存header信息;本次請求根本就不會與服務器進行通信

如果沒有命中強緩存,瀏覽器會發送請求到服務器,請求會攜帶第一次請求返回的有關緩存的header字段信息(Lase-Modified/If-Modified-SinceEtag/If-Node-Match),由 服務器根據請求中的相關header信息來比對結果是否協商緩存命中;

若命中,則服務器返回新的響應header信息更新緩存中的對應header信息,但是並不返回資源內容,它會告知瀏覽器可以直接從緩存獲取,否則返回最新的資源內容。

緩存參考文章

juejin.im/post/5b3c87…

頁面渲染速度優化(用戶體驗優化)

  • css放在頂部,優先渲染。
  • js放在底部,避免堵塞,減少白屏時間和首頁渲染時間。
  • 減少DOM數量,減少重排重繪。
  • Virtual Dom。
  • 預加載和懶加載。
  • 骨架屏。

避免JS堵塞

使用async和defer,async不支持ie9,所以首推薦使用defer,如果使用defer或async請將script標籤放到head標籤中,以便讓瀏覽器更早地發現資源並在後臺線程中解析並加載JS

重排重繪

  1. 重排(reflow):渲染層內的元素佈局發生修改,都會導致頁面重新排列,比如窗口的尺寸發生變化,刪除或添加DOM元素,修改了影響元素盒子大小的css屬性(width,height,padding)

  2. 重繪(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會提升性能和代碼可閱讀和維護性。

  • 函數的防抖節流

    justclear.github.io/throttle-an…

  • 事件委託的有點

    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(國外開源的錯誤監控,有線上環境也可以自行部署)

sentry官網

sentry跟Vue搭配

自動化構建、持續集成

Travis CI(對Github支持很友好)

阮一峯Travis CI教程

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章