轉自:https://www.jianshu.com/p/fe32ef31deedjavascript
前言php
對於前端的性能話題,歷來都沒有斷絕過。由於這個東西沒有最好,只有更好。並且每每也是業務的繁雜程度去決定優化程度的。做爲一個前端開發者,性能是咱們關注的指標。它直接影響着咱們的用戶,同時也影響着產品自己。前端發展以來,優化方式,琳琅滿目,有雅虎軍規等。這些內容複雜繁多,每每容易被人遺忘。所以,本篇對於這些經常使用的優化方式進行總結,或許,並不全面,見諒。若是你喜歡個人文章,歡迎評論,歡迎Star~。css
前端優化層出不窮,移動端大行其道的如今,咱們能夠說優化好移動端,PC端也將會更好。因此,咱們能夠綜合如下圖片進行一些分析,如圖:前端
圖中已經對前端性能作了一些歸納。但其實,我以爲咱們能夠將這個歸納更加精準,扼要,豐富。因此,接下來我會從三個方面就前端性能進行總結:網絡方面、DOM操做及渲染方面、數據方面。java
web應用,老是會有一部分的時間浪費在網絡鏈接和資源下載方面。每每創建一次網絡鏈接是須要時間成本的。並且瀏覽器同一時間所發送的網絡請求數是有限的。因此,這個層面的優化能夠從「減小請求數目」開始:android
減小http請求:在YUI35規則中也有提到,主要是優化js、css和圖片資源三個方面,由於html是沒有辦法避免的。所以,咱們能夠作一下的幾項操做:webpack
上述四個方法,前面二者咱們可使用webpack之類的打包工具進行打包;雪碧圖的話,也有專門的製做工具;圖片的編碼是使用base64的,因此,對於一些簡單的圖片,例如空白圖等,可使用base64直接寫入html中。ios
回到以前網絡層面的問題,除了減小請求數量來加快網絡加載速度,每每整個資源的體積也是,平時咱們會關注的方面。程序員
減少資源體積:能夠經過如下幾個方面進行實施:
gzip壓縮主要是針對html文件來講的,它能夠將html中重複的部分進行一個打包,屢次複用的過程。js的混淆能夠有簡單的壓縮(將空白字符刪除)、醜化(醜化的方法,就是將一些變量縮小)、或者可使用php對js進行混淆加密。css壓縮,就是進行簡單的壓縮。圖片的壓縮,主要也是減少體積,在不影響觀感的前提下,儘可能壓縮圖片,使用png等圖片格式,減小矢量圖、高清圖等的使用。這樣子的作法不只能夠加快網頁顯示,也能減小流量的損耗。
除了以上兩部分的操做以外,在網絡層面咱們還須要作好緩存工做。真正的性能優化來講,緩存是效率最高的一種,每每縮短的加載時間也是最大的。
緩存:能夠經過如下幾個方面來描述:
因爲瀏覽器會在DNS解析步驟中消耗必定的時間,因此,對於一些高訪問量網站來講,作好DNS的緩存工做,就會必定程度上提高網站效率。CDN緩存,CDN做爲靜態資源文件的分發網絡,自己就已經提高了,網站靜態資源的獲取速度,加快網站的加載速度,同時也給靜態資源作好緩存工做,有效的利用已緩存的靜態資源,加快獲取速度。http緩存,也是給資源設定緩存時間,防止在有效的緩存時間內對資源進行重複的下載,從而提高總體網頁的加載速度。
其實,網絡層面的優化還有不少,特別是針對於移動端頁面來講。衆所周知,移動端對於網絡的敏感度更加的高,除了目前的4G和WIFI以外,其餘的移動端網絡至關於弱網環境,在這種環境下,資源的緩存利用是至關重要的。並且,減小http的請求次數,也是相當重要的,移動端弱網環境下,對於http請求的時間也會增長。因此,咱們能夠看一下咱們在移動端網絡方面能夠作的優化:
移動端優化:使用如下幾種方式來加快移動端網絡方面的優化:
「使用長cache」,可使得移動端的部分資源設定長期緩存,這樣能夠保證資源不用向服務器發送請求,來比較資源是否更新,從而避免304的狀況。304重定向,在PC端或許並不會影響網頁的加載速度,可是,在移動端網絡不穩定的前提下,多一次請求,就多了一部分加載時間。「首屏優化」,對於移動端來講是相當重要的。2s時間是用戶的最佳體驗,一旦超出這個時間,將會致使用戶的流失。因此,針對移動端的網絡狀況,不可能在這麼短期內加載完成全部的網頁資源,因此咱們必須保證首屏中的內容被優先顯示出來,並且基於TCP的慢啓動和擁塞控制,第一個14kb的數據是很是重要的,因此須要保證首部加載數據可以小於14kb。「不濫用web字體」,web字體的好處就是,能夠代替某些圖片資源,可是,在移動端過多的web字體的使用,會致使頁面資源加載的繁重,因此,慎用web字體
首先,簡單的聊一下優化渲染的重要性。在網頁初步加載時,獲取到HTML文件以後,最初的工做是構建DOM和構建CSSOM兩個樹,以後將他們合併造成渲染樹,最後對其進行打印。咱們能夠經過圖片來看一下,簡單的過程:
這裏整個過程拉出來寫,具體能夠再寫一篇文章,恕我偷下懶,推薦一篇比較好的文章給你們吧。瀏覽器渲染過程與性能優化
繼續咱們的話題,咱們能夠如何去縮短這個過程呢?能夠從如下幾個操做進行優化。
優化網頁渲染:
css文件放在「頭部加載」,能夠保證解析DOM的同時,解析css文件。由於,CSS(外鏈或內聯)會阻塞整個DOM的渲染,然而DOM解析會正常進行,因此將css文件放在頭部進行解析,能夠加快網頁的構建速度。假設將其放在尾部,那時DOM樹幾乎構建,這時就得等到CSSOM樹構建完成,纔可以繼續下面的步驟。「js放在尾部」:js文件不一樣,將js文件放在尾部或者異步加載的緣由是JS(外鏈或內聯)會阻塞後續DOM的解析,後續DOM的渲染也將被阻塞,並且一旦js中遇到DOM元素的操做,極可能會影響。這方面能夠推薦一篇文章——異步腳本載入提升頁面性能。「避免使用內聯樣式」,能夠有效的減小html的體積,通常考慮內聯樣式的時候,每每是樣式自己體積比較小,每每加載網絡資源的時間會大於它的時候。
除了頁面渲染層面的優化,固然最重要的就是DOM操做方面的優化,這部分的優化應該是最多的,並且也是平時開發能夠注意的地方。若是開發前期明白這些原理,同時付諸實踐的話,就能夠在後期的性能完善上面少下不少功夫。那麼,接下來咱們能夠來看一下具體的操做:
DOM操做優化:
前面三個操做,其實都是但願『減小回流和重繪』。其實,進行一次DOM操做的代價是很是之大的,之前能夠經過網頁操做是否卡頓來進行判斷,可是,現代瀏覽器的進步已經大大減小了這方面的影響。可是,咱們仍是須要清楚,如何去減小回流和重繪的問題。由於這裏不想細說這方面的知識,想要了解的話,能夠看這篇文章——迴流與重繪:CSS性能讓JavaScript變慢?。這但是張鑫旭大大的一篇文章呦(^.^)。「儘可能使用css動畫」,是由於自己css動畫比較簡單,並且相較於js的複雜動畫,瀏覽器自己對其進行了優化,使用上面不會出現卡頓等問題。「使用requestAnimationFrame代替setInterval操做」,相信你們都有所耳聞,setInterval定時器會有必定的延時,對於變更性高的動畫來講,會出現卡頓現象。而requestAnimationFrame正好解決的整個問題。「適當使用canvas」,不得不說canvas是前端的一個進步,出現了它以後,前端界面的複雜性也隨之提高了。一些難以完成的動畫,均可以使用canvas進行輔助完成。可是,canvas使用頻繁的話,會加劇瀏覽器渲染的壓力,同時致使性能的降低。因此,適當時候使用canvas是一個不錯的建議。「儘可能減小css表達式的使用」,這個在YUI規則中也被提到過,每每css的表達式在設計之初都是美好的,但在使用過程當中,因爲其頻繁觸發的特性,會拖累網頁的性能,出現卡頓。所以在使用過程當中儘可能減小css表達式的使用,能夠改換成js進行操做。「使用事件代理」:每每對於具有冒泡性質的事件來講,使用事件代理不失爲一種好的方法。舉個例子:一段列表都須要設定點擊事件,這時若是你給列表中的每一項設定監聽,每每會致使總體的性能降低,可是若是你給整個列表設置一個事件,而後經過點擊定位目標來觸發相應的操做,每每性能就會獲得改善。
DOM操做的優化,還有不少,固然也包括移動端的。這個會在以後移動端優化部分被說起,此處先賣個關子。上面咱們概述了開始渲染的時候和DOM操做的時候的一些注意事項。接下來要講的是一些小細節的注意,這些細節可能對於頁面影響不大,可是一旦堆積多了,性能也會有所影響。
操做細節注意:
上述的一些操做細節,是平時在開發中被要求的,更能夠理解爲開發規範。(基本操做,坐下^_^)
列舉完基本操做以後,咱們再來聊一下移動端在DOM操做方面的一些優化。
移動端優化:
首先,長列表滾動問題,是移動端須要面對的,IOS儘可能使用局部滾動,android儘可能使用全局滾動。同時,須要給body添加上-webkit-overflow-scrolling: touch來優化移動段的滾動。若是有興趣的同窗,能夠去了解一下ios和android滾動操做上的區別以及優化。「防抖和節流」,設計到滾動等會被頻繁觸發的DOM事件,須要作好防抖和節流的工做。它們都是爲了限制函數的執行頻次,以優化函數觸發頻率太高致使的響應速度跟不上觸發頻率,出現延遲,假死或卡頓的現象。
介紹:函數防抖,當調用動做過n毫秒後,纔會執行該動做,若在這n毫秒內又調用此動做則將從新計算執行時間;函數節流,預先設定一個執行週期,當調用動做的時刻大於等於執行週期則執行該動做,而後進入下一個新週期。
「touchstart、touchend代替click」,也是移動端比較經常使用的操做。click在移動端會有300ms延時,這應該是一個常識唄。(不知道的小夥伴該收藏一下呦)。這種方法會影響用戶的體驗。因此作優化時,最簡單的方法就是使用touchstart或者touchend代替click。由於它們事件執行順序是touchstart->touchmove->touchend->click。或者,使用fastclick或者zepto的tap事件代替click事件。「HTML的viewport設置」,能夠防止頁面的縮放,來優化性能。「開啓GPU渲染加速」,小夥伴們必定聽過CPU吧,可是這裏的GPU不能和CPU混爲一談呦。GPU的全名是Graphics Processing Unit,是一種硬件加速方式。通常的css渲染,瀏覽器的渲染引擎都不會使用到它。可是,在3D渲染時,計算量較大,繁重,瀏覽器會開啓顯卡的硬件加速來幫助完成這些操做。因此,咱們這裏可使用css中的translateZ設定,來欺騙瀏覽器,讓其幫忙開啓GPU加速,加快渲染進程。
DOM部分的優化,更多的是習慣。須要本身強制要求本身在開發過程當中去注意這些規範。因此,這部分的內容能夠多關注一下,纔可以慢慢了解。同時,本人對於上述幾點的描述是歸納性的。並無對其進行詳細的展開。所以,也要求你去細細的查閱Google呦。
數據,也能夠說是前端優化方面比較重要的一塊內容。頁面與用戶的交互響應,每每伴隨着數據交互,處理,以及ajax的異步請求等內容。因此,咱們也能夠來聊聊這一塊的知識。首先是對於圖片數據的處理:
圖片加載處理:
「圖片預加載」,預加載的寓意就是提早加載內容。而圖片的預加載每每會被用在圖片資源比較大,即時加載時會致使很長的等待過程時,纔會被使用的。常見場景:圖片漫畫展現時。每每會預加載一張到兩張的圖片。「圖片懶加載」,懶加載或許你是第一次據說,可是,這種方式在開發中會被常用。首先,咱們須要明白一個道理:每每只有看到的資源是必須的,其餘資源是能夠隨着用戶的滾動,隨即顯示的。因此,特別是對於圖片資源特別多的網站來講,作好圖片的懶加載是能夠大大提高網頁的載入速度的。
常見的圖片懶加載的方式就是:在最初給圖片的src設置一個比較簡單的圖片,而後將圖片的真實地址設置給自定義的屬性,作一個佔位,而後給圖片設置監聽事件,一旦圖片到達視口範圍,從圖片的自定義屬性中獲取出真是地址,而後賦值給src,讓其進行加載。
「首屏進度條的顯示」:每每對於首屏優化後的數據量並不滿意的話,同時也不能進一步縮短首屏包的長度了,就可使用進度條的方式,來提醒用戶進行等待。
講完了圖片這一塊數據資源的處理,每每咱們須要去優化一下異步請求這一部分的內容。由於,異步的數據獲取也是前端不可分割的。這一部分咱們也能夠作必定的處理:
異步請求的優化:
「JSON交互」,JSON的數據格式輕巧,結構簡單,每每能夠大大優化先後端的數據通訊。「經常使用數據的緩存」,能夠將一些用戶的基本信息等經常使用的信息作一個緩存,這樣能夠保證ajax請求的減小。同時,HTML5新增的storage的內容,也不用怕cookie暴露,引發的信息泄漏問題。「數據埋點和統計」,對於資深的程序員來講,比較瞭解。並且目前的大部分公司也會作這方面的處理。有心的小夥伴能夠自行查閱。
最後,還有就是大量數據的運算。對於javascript語言來講,自己的單線程就限制了它並不能計算大量的數據,每每會形成頁面的卡頓。而可能業務中有些複雜的UI須要去運行大量的運算,因此,webWorker的使用是相當重要的。或許,前端標準普及的落後,會致使你們對於這些新生事物的短暫缺失吧。
本篇文章就前端性能這個話題作了一個總結。或許,並不全面,可是都是一些平時開發中會被常常用到的知識。但願有心者可以去親身的嘗試一下這些方面的優化。本篇的概述了一下幾個知識點: