標籤:

前端性能優化

前端性能優化涉及很多方面,今天準備寫一篇文章做一個縱覽的總結。

文章會從 程序性能優化 資源分配優化 傳輸性能優化 用戶體驗優化四個大的角度來解析前端性能優化。

程序性能優化

當代前端有兩大驅動的開發模式,分別是以DOM為驅動的傳統開發模式和以數據為驅動的MVVM開發模式;這兩種開發模式分別面臨著各自的性能優化問題,除了針對這兩種開發模式的性能優化之外還有一些編程細節的性能優化方法。

以DOM為驅動的性能優化:減少或合併DOM操作

眾所周知,DOM操作是前端程序中最耗費資源的編程操作。示例代碼如下:

// 不好的方式//var elem = $(#elem);//for (var i = 0; i < 100; i++) {// elem.append(<li>element +i+</li>);//}// 好的方式var elem = $(#elem ),arr = [];for (var i = 0; i < 100; i++) { arr.push(<li>element +i+</li> );}elem.append(arr. join());

事實上,最新的MVVM框架紛紛對自家的文檔操作中實現了虛擬DOM,通過Diff演算法來減少真實DOM操作的壓力。

以數據為驅動的性能優化:優化數據結構

前端MVVM框架以數據為驅動進行開發,則需要對問題抽象出合適的邏輯結構,選擇合適的數據結構,再通過高效的演算法實現。

比如在實際項目中盡量不要使用以前演算法課上學的「冒泡排序 選擇排序」,而使用Array.prototype.sort()方法,以V8引擎為例,不嚴謹的說,它的演算法跟數組的長度有關,當數組長度小於等於 10 時,採用插入排序,大於 10 的時候,採用快速排序。時間複雜度在最好的情況下可以達到O(n).

其他一些細節:對大量重複事件使用事件代理 對大量數據計算使用緩存 減少無必要的大量觸發事件操作等

如一篇我以前文章事件中所提到的事件代理機制,綁定一個元素使用事件代理比綁定100個小事件更加節約性能。

又有如下例子:

// data.length === 100000for(var i = 0;i < data.length;i++){ // do something...}//上面的代碼沒有下面的好for(var i = 0,len = data.length;i < len;i++){ // do something...}

因為length是通過.next()方法一個一個數出來的,所以可以把它賦值給一個緩存len,以後每次重複需要這個量的時候只需要調用緩存就行了。

還有一些情況,常見於觸發滾動事件時,滾動事件每滾動一個像素就會觸發一次,為了防止它過於頻繁的觸發,常常使用setTimeout()方法來降低它調用的頻率,每隔一定時間段才觸發。

資源分配優化

上海交通大學楊斌老師的《軟體工程》課程指出,現代軟體發展瓶頸之一在於網路傳輸速度的瓶頸。這也就意味著在我們設計前端工程的時候要考慮如何根據線性的網路傳輸速度平均分配資源的展現量來緩解用戶的焦慮————事實上這樣做如果載入的是動態資源還有助於緩解伺服器壓力,從未來的角度思考,甚至可能幫助緩解客戶端內存和磁碟讀寫壓力。

分頁 懶載入

使用分頁和懶載入的方法在這裡不再贅述了,谷歌一下能夠得到一大堆的實現方法。這裡主要提示三個點:

  1. 分頁和懶載入的單頁數據數量要選擇適合,滿足一個節拍的瀏覽體驗,太短讓人感覺沒刷兩頁就載入,影響心流;太多則導致載入時間問題。
  2. 對於懶載入,選擇合適的佔位元素是關鍵。因為不選擇佔位元素,往往會導致文檔結構展示沒有預期設計稿的架構,如果CSS編寫者功力不夠,甚至會產生整個文檔的錯位。
  3. 對於分頁,要確認是前端處理分頁還是後端處理分頁。這往往根據團隊規劃,伺服器處理能力而定。事實上很多問題的處理都應該思考這兩點。

單頁應用基於路由的懶載入

以Vue為例,有

// import Foo from ./Foo.vueconst Foo = resolve => require([./Foo.vue], resolve)

因為webpack的流行,很容易以Promise的形式實現基於路由的懶載入和自動的封裝打包。

預載入

所謂「預載入」僅僅是一種思路,有多種實踐方法,往往用於圖片音樂視頻等大的靜態資源上。

小到在曝光載入時將載入時間略提前於曝光,大到WebApp先載入後運行,都可以稱之為「預載入」。

傳輸性能優化

前端工程的最典型特徵在於他是非同步的,互聯網化的,所以針對『傳輸』這一關鍵點進行優化往往是最直接,最有效的方法。

選擇合適的通信協議

在需要伺服器主動發布信息的情況下,盡量使用Websocket而不是Ajax輪詢。往往能獲得更加的用戶通信體驗和性能。

壓縮合併資源:減小請求內容大小和請求數

最直觀的,靜態資源的大小和多少直接制約了載入的速度,對靜態資源的壓縮合併打包也顯得必要起來。

早期的前端常常是切圖仔在線手動壓縮合併js,css,用圖片處理軟體手動降低圖片質量,例如像在下面的網址:

在線 JS/CSS/HTML 壓縮

再後來,前端工程化思想成型,人們開始使用gulp之類的前端工作流處理工具進行壓縮合併處理:

gulp使用:進行壓縮合併js、css - MartinL - 博客園

到了現在,我們最常用的往往是Webpack來進行模塊打包,合併壓縮。

不僅如此,Webpack甚至可以實現分塊打包,按需載入,代碼熱修改等高級功能:

基於webpack的前端工程化開發解決方案探索(三):webpack-dev-server - 小俠同學 - 博客園

使用CDN傳輸靜態資源

CDN的全稱是Content Delivery Network,即內容分發網路。其基本思路是儘可能避開互聯網上有可能影響數據傳輸速度和穩定性的瓶頸和環節,使內容傳輸的更快、更穩定。通過在網路各處放置節點伺服器所構成的在現有的互聯網基礎之上的一層智能虛擬網路,CDN系統能夠實時地根據網路流量和各節點的連接、負載狀況以及到用戶的距離和響應時間等綜合信息將用戶的請求重新導向離用戶最近的服務節點上。其目的是使用戶可就近取得所需內容,解決 Internet網路擁擠的狀況,提高用戶訪問網站的響應速度。

及時使用CDN可以有效的減少靜態資源載入速度。當然,動態資源是嚴禁CDN的,當然,CDN還有其他的一些妙用:比如Github禁止百度爬蟲爬取GithubPages的內容,這個時候可以選擇把自己GithubPages上的內容分發到CDN上,這樣就可以正確的爬取CDN上的資源然後定向到你的頁面了。

啟用伺服器壓縮方案:gzip等

流行的伺服器往往都配備了gzip壓縮方案,開啟它往往不超過幾行配置,卻可以降低三分之二的流量消耗。

採用合適的緩存方案

不經常更新的內容盡量定義長時間的緩存時間,不但能減少伺服器的壓力,還可以優化用戶的體驗。即使是更新頻繁的資源也盡量使用Etag頭的方法進行緩存更新來讓伺服器資源獲得有效利用。

用戶體驗優化

通過良好的設計雖然不能直接提高軟體性能,但是可以有效的緩解用戶焦慮,提高即時數據利用率等。

採用進度條等手段解決「無響應錯覺」

進度條最初的設計是用來提醒操作者「我們在進行一些後台的操作,並不是死機了」,直到現在這一經典設計仍舊被沿用。不確定的等待時間比已知的、有限的等待時間讓人覺得更長。在一些情況下,並不適用動畫載入,如載入H5,上傳文件,人們會因無法預知載入時間長短而感到煩躁。你應該給你的用戶一個清晰地等待時間,讓用戶盯著一個下載進度條會讓跳出率降低。

採用提前展現內容等方法

即使內容不能點擊,也把獲得的信息先呈現給用戶之後再載入內容或點擊事件,這樣的操作增加了信息流在時間線性程度上的價值。

優秀的交互設計

我個人最喜歡的交互設計框架當屬螞蟻金服的Antd,下面提供一個鏈接以飱各位

A UI Design Language

綜合優化策略————優先補充短板

一隻木桶能盛多少水,並不取決於最長的那塊木板,而是取決於最短的那塊木板。也可稱為短板效應。任何一個前端架構,可能面臨的一個共同問題,即構成工程的各個部分往往是優劣不齊的,而劣勢部分往往決定整個工程的水平。因此,每個人都應思考一下「短板」的位置,並儘早補足它。

附:前端性能測試工具網站

Website Performance and Optimization Test

developers.google.com/s

更多文章請關注:blog.zain.red


推薦閱讀:

當我們在談論前端加密時,我們在談些什麼
極樂技術周報(第二十期)
開發者和用戶之間的世界觀距離有多大?
前端系列教學(入門篇) - 響應式設計(2)

TAG:前端开发 |