前端效能常見優化點分析

jacintoface發表於2018-07-07

前言

網站的劃分一般為二:前端和後臺。我們可以理解成後臺是用來實現網站的功能的,比如:實現使用者註冊,使用者能夠為文章發表評論等等。而前端呢?其實應該是屬於功能的表現。並且影響使用者訪問體驗的絕大部分來自前端頁面。

而我們建設網站的目的是什麼呢?不就是為了讓目標人群來訪問嗎?所以我們可以理解成前端才是真正和使用者接觸的。除了後臺需要在效能上做優化外,其實前端的頁面更需要在效能優化上下功夫,只有這樣才能給我們的使用者帶來更好的使用者體驗。就好像,好多人問,男人在找女朋友的時候是不是隻看外表,一些智慧的男人給出了這樣的回答:臉蛋和身材決定了我是否想去了解她的思想,思想決定了我是否會一票否決她的臉蛋和身材。同理,網站也是這樣,網站前端的使用者體驗決定了使用者是否想要去使用網站的功能,而網站的功能決定了使用者是否會一票否決前端體驗。

不僅僅如此,如果前端優化得好,他不僅可以為企業節約成本,他還能給使用者帶來更多的使用者,因為增強的使用者體驗。說了這麼多,那麼我們應該如何對我們前端的頁面進行效能優化呢?

一般說來,web前端指網站業務邏輯之前的部分,包括瀏覽器載入、網站檢視模型、圖片服務、CDN服務等,主要優化手段有瀏覽器訪問、CDN、服務端渲染以及http相關等等。

但是做效能優化有一點是很重要的,就是各個方法之間的balance,我們不能以為我們使用了某個方法,網頁體驗就能更好,載入速度就能更快,所有的效能改進方法都要以實際體驗為準。

1、請減少HTTP請求以及dns優化:

在瀏覽器(客戶端)和伺服器發生通訊時,就已經消耗了大量的時間,尤其是在網路情況比較糟糕的時候,這個問題尤其的突出。

一個正常HTTP請求的流程簡述:如在瀏覽器中輸入"www.xxxxxx.com"並按下回車,瀏覽器再與這個URL指向的伺服器建立連線,然後瀏覽器才能向伺服器傳送請求資訊,伺服器在接受到請求的資訊後再返回相應的資訊,瀏覽器接收到來自伺服器的應答資訊後,對這些資料解釋執行。

而當我們請求的網頁檔案中有很多圖片、CSS、JS甚至音樂等資訊時,將會頻繁的與伺服器建立連線,與釋放連線,這必定會造成資源的浪費,且每個HTTP請求都會對伺服器和瀏覽器產生效能負擔。

網速相同的條件下,下載一個100KB的圖片比下載兩個50KB的圖片要耗費的網路資源更多。所以,請減少HTTP請求。

解決辦法:

  1. 資源的合併與壓縮

合併CSS和JS檔案,css壓縮以及js壓縮,在當前的前端生態中,我們可以結合webpack等工具自動幫我們做壓縮,比如uglyfy-js等工具,甚至是利用tree shaking等功能去自動幫我們精簡程式碼,但是請注意,不能過度合併資源,否則會造成首頁載入過慢的問題。

  1. 圖片處理
    1. 選擇合適的圖片型別,如對色彩要求不嚴格,我們可以考慮使用jpg,不用支援透明我們可以考慮使用png24,支援webp格式優先考慮使用webp格式(android上對webp支援較好,ios支援較差,現在淘寶是採用這種模式,)
    1. 小圖片採用base64的格式,直接嵌入程式碼中,可以幫我們減少http請求,但是同樣,這個會造成我們程式碼的提及變大,請求的速度會減慢,這個就是上面所說的需要一個balance,現在精靈圖的方式已經不是特別流行了,目前大網際網路站只發現Facebook在使用
    1. 使用圖片預載入和圖片懶載入,對於類似瀑布流佈局或電商等圖片較多的網站,合理使用圖片預載入的方式可以使首頁可以更加快速開啟,並且減少頻寬消耗
    1. 對於 小icon,我們可以考慮使用字型圖示,它比圖片更輕量級並且更好控制

2、請正確理解 Repaint 和 Reflow已經圖層等概念

  • Repaint(重繪)就是在一個元素的外觀被改變,但沒有改變佈局(寬高)的情況下發生,如改變visibility、outline、背景色等等。

  • Reflow(迴流)就是DOM的變化影響到了元素的幾何屬性(寬和高),瀏覽器會重新計算元素的幾何屬性,會使渲染樹中受到影響的部分失效,瀏覽器會驗證DOM樹上的所有其它結點的visibility屬性,這也是Reflow低效的原因。如:改變窗囗大小、改變文字大小、內容的改變、瀏覽器視窗變化,style屬性的改變等等。如果Reflow的過於頻繁,CPU使用率就會噌噌的往上漲,所以前端也就有必要知道 Repaint 和 Reflow的知識。

迴流一定會重繪,但是重繪不一定會造成迴流,所以如果可以實現相同效果,採用重繪的方式可以幫我節省迴流的時間

比如上面提到通過設定style屬性改變結點樣式的話,每設定一次都會導致一次reflow,所以最好通過設定class的方式; 有動畫效果的元素,它的position屬性應當設為fixed或absolute,這樣不會影響其它元素的佈局;如果功能需求上不能設定position為fixed或absolute,那麼就權衡速度的平滑性。還有比如動畫使用translate的方式而不是用定位的方式,透明度使用rgba而不用使用opacity等,有些不經意的操作也會導致大量回流,如在迴圈中使用offsetWidth等。

圖層: 瀏覽器會為經常變化的部分形成一個圖層,比如video等,我們可以通過chrome的layout工具找到圖層,形成一個新圖層可以讓瀏覽器只回流變化的部分,比如使用will-change可以將一個元素新建一個圖層,對於gif等變化較多的我們可以考慮使用新建圖層的方式,但是注意圖層過多也會導致圖層合成的時候花費大量時間。

3、請減少對DOM的操作

基本原理:對DOM操作的代價是高昂的,這在網頁應用中的通常是一個效能瓶頸。

天生就慢。在《高效能JavaScript》中這麼比喻:“把DOM看成一個島嶼,把JavaScript(ECMAScript)看成另一個島嶼,兩者之間以一座收費橋連線”。所以每次訪問DOM都會教一個過橋費,而訪問的次數越多,交的費用也就越多。所以一般建議儘量減少過橋次數。

解決辦法:

  • 1.修改和訪問DOM元素會造成頁面的Repaint和Reflow,迴圈對DOM操作更是罪惡的行為。所以請合理的使用JavaScript變數儲存內容,考慮大量DOM元素中迴圈的效能開銷,在迴圈結束時一次性寫入。

  • 2.減少對DOM元素的查詢和修改,查詢時可將其賦值給區域性變數,使用innerHTML的方式一次插入。

    1. 考慮使用前端mv*框架

4. 使用CDN加速(內容分發網路)

基本原理:

CDN的全稱是Content Delivery Network,即內容分發網路。

簡單來說它主要的工作是把我們需要被分發的內容分發到世界各地的各個節點上,讓世界各地的人都可以在距離最近的網路節點拿到想要拿到的內容,減少網路傳輸距離從而達到加速的目的。

當使用者發起內容請求時,通過cdn廠商的智慧DNS域名解析拿到cdn廠商邊緣節點伺服器的ip(cdn廠商會在運營商註冊),然後向邊緣節點伺服器發起請求,請求內容資料(這件事情由瀏覽器完成),邊緣節點會檢測當前節點是否有資料,如果沒有就去front(父級節點,父級可能還會有父級節點,不同的網路環境策略會略有不同)節點要,如果還找不到就去源站拿,並依次序返回。如果某個邊緣節點可以找到,會先校驗內容有效期,當確定有效期之後返回給使用者

但是使用CDN的方式請注意瀏覽器有有一個同域名併發請求上限,所以如果cdn資源過多,我們可以考慮使用多個cdn域名

5.將CSS和JS放到外部檔案中引用,CSS放頭,JS放尾

基本原理:

引入外部檔案好處是顯而易見的,而且是專案稍稍複雜一點的時候就有必要了這樣做了,易維護、易擴充套件,方便管理和重複利用。

正確的方式:

JavaScript是瀏覽器中的霸主,為什麼這麼說,因為在瀏覽器在執行JavaScript程式碼時,不能同時做其它事情,即每次出現都會讓頁面等待指令碼的解析和執行(不論JavaScript是內嵌的還是外鏈的),JavaScript程式碼執行完成後,才繼續渲染頁面。這個也就是JavaScript的阻塞特性。因為這個阻塞的特點,建議把JavaScript程式碼放到標籤以前,這樣既能有效的防止JavaScript的阻塞,又能使得頁面的HTML結構能更快的釋放。

HTML規範清楚指出CSS要放包含在頁面的區域內,這裡就不多解釋了。

但是有點需要注意,瀏覽器js會阻止html的渲染,但是我們為什麼可以載入js下面的資源呢?其實瀏覽器內部也是有一個資源請求的預檢機制的,可以在js執行時併發的請求資源

5、在前端框架中使用非同步載入以及服務端渲染

  1. 為什麼需要非同步載入

現在流行的使用webpack的工具構建的前端工程,可以合併我們的js和css以及image等資源,合併為一個檔案,那麼是不是我們減少了http請求的數量那我們網站的效能優化就更好了呢?no,可能我們網站靜態資源很多,全部揉進一個js檔案,那這個檔案會是非常巨大的,首頁資源載入的速度會非常慢,那麼有什麼辦法可以優化呢?答案是非同步載入,我們不打包所有的元件檔案,將檔案拆分開來,當我們使用到這個元件的時候,我們才去載入,通常我們配合webpack以及非同步載入方法import('a.js')

  1. 服務端渲染

客戶端渲染和伺服器端渲染的最重要的區別就是究竟是誰來完成html檔案的完整拼接,如果是在伺服器端完成的,然後返回給客戶端,就是伺服器端渲染,而如果是前端做了更多的工作完成了html的拼接,則就是客戶端渲染, 例如我們在react中我們可以使用renderToString將元件渲染為html

優點:

  • 首屏載入快

相比於載入單頁應用,我只需要載入當前頁面的內容,而不需要像 React 或者 Vue 一樣載入全部的 js 檔案(當然,單頁應用檔案載入過大的情況可以使用 code spliting 來解決

  • SEO 優化

對於單頁應用,搜尋引擎並不能收錄到 ajax 爬取資料之後然後再動態 js 渲染出來的頁面

6. 使用快取和客戶端本地儲存

對於很少變化的靜態資源,我們可以考慮使用快取,並且設定一定的過期時間,可以有效的提升頁面的載入速度和頻寬的節約

相關文章