發(fā)布時間:2017/9/6 18:00:01
很多人通常在完成了產(chǎn)品之后才會去考慮性能。把與性能相關(guān)的事情拖到項目的最后來做,所做的也不過是對服務(wù)器上的config文件進(jìn)行一些微調(diào)、串聯(lián)、優(yōu)化以及部分特別小的調(diào)整。而現(xiàn)在,技術(shù)已經(jīng)有了翻天覆地的變化。一個項目的性能是非常重要的,除了要在技術(shù)層面上注意,更要在項目的設(shè)計之初就開始考慮,這樣才可以使性能的各種隱形需求完美的整合到項目中,隨著項目一起推進(jìn)。
在性能方面,前端的優(yōu)化是大家很容易忽視卻又十分重要的一點。
前端是龐大的,包括 HTML、 CSS、 Javascript、Image 、Flash等等各種各樣的資源。前端優(yōu)化是復(fù)雜的,針對方方面面的資源都有不同的方式。那么,前端優(yōu)化的目的是什么 ?
? 從用戶角度而言,優(yōu)化能夠讓頁面加載得更快、對用戶的操作響應(yīng)得更及時,能夠給用戶提供更為友好的體驗。前端優(yōu)化的途徑有很多,按粒度大致可以分為三類:
第一類是頁面級別的優(yōu)化,例如 HTTP請求數(shù)、腳本的無阻塞加載、內(nèi)聯(lián)腳本的位置優(yōu)化等 ;
第二類是服務(wù)器端優(yōu)化,如:添加Expires 或Cache-Control報文頭等;
第三類則是代碼級別的優(yōu)化,例如 Javascript中的DOM 操作優(yōu)化、CSS選擇符優(yōu)化、圖片優(yōu)化以及 HTML結(jié)構(gòu)優(yōu)化等等。
【頁面級優(yōu)化】
一、減少 HTTP請求數(shù)
80%的響應(yīng)時間花在下載網(wǎng)頁內(nèi)容(images, stylesheets, javascripts, scripts, flash等)。減少請求次數(shù)是縮短響應(yīng)時間的關(guān)鍵!可以通過簡化頁面設(shè)計來減少請求次數(shù),但頁面內(nèi)容較多可以采用以下技巧。
1)捆綁文件
現(xiàn)在有很多現(xiàn)成的庫可以幫你將多個腳本文件捆綁成一個文件,將多個樣式表文件捆綁成一個文件,以此來減少文件的下載次數(shù)。
2)CSS Sprites
就是把多個圖片拼成一副圖片,然后通過CSS來控制在什么地方具體顯示這整張圖片的什么位置。
咱們來看一個真實的應(yīng)用案例,如圖1:
從圖1可以看到這個應(yīng)用的所有css和js都沒有沒有合并壓縮,我算了一下,總共引入了50個css和js,咱們再開看看圖2:
從圖2可以看出,一個頁面加載最少要4秒,每個css資源http請求就用了兩百多毫秒,50個資源就占了一秒多。如果把所有js和css分別合并壓縮成一個文件,頁面的加載速度就會提高很多。
現(xiàn)在壓縮合并js和css的工具很多,但是考慮到現(xiàn)在好多項目都是maven工程,所以推薦大家使用雅虎的yuicompressor工具進(jìn)行壓縮合并,還可以打出API文檔(jresui的API文檔就是用這個來打的), yuicompressor除了支持maven方式,也支持后臺java代碼方式進(jìn)行合并壓縮,具體配置如下:
▲將外部腳本置底,將CSS放在head中
瀏覽器是可以并發(fā)請求的,這一特點使得其能夠更快的加載資源,然而外鏈腳本在加載時卻會阻塞其他資源。如果將腳本放在比較靠前的位置,則會影響整個頁面的加載速度從而影響用戶體驗。解決這一問題的方法有很多,而最簡單可依賴的方法就是將腳本盡可能的往后挪,減少對并發(fā)下載的影響。
如果將 CSS放在其他地方比如 BODY中,則瀏覽器有可能還未下載和解析到 CSS就已經(jīng)開始渲染頁面了,這就導(dǎo)致頁面由無 CSS狀態(tài)跳轉(zhuǎn)到 CSS狀態(tài),用戶體驗比較糟糕。除此之外,有些瀏覽器會在 CSS下載完成后才開始渲染頁面,如果 CSS放在靠下的位置則會導(dǎo)致瀏覽器將渲染時間推遲。
二、靜態(tài)資源緩存
我們知道,緩存對于前端性能的優(yōu)化是十分重要的,在正式發(fā)布系統(tǒng)的時候,對于那些不經(jīng)常變動的靜態(tài)資源比如各種JS、CSS文件、背景圖片等等我們會設(shè)置一個比較大的緩存過期時間(max-age),當(dāng)用戶再次訪問這個頁面的時候就可以直接利用緩存而不是重新從服務(wù)器獲取,這樣不僅可以減輕服務(wù)端的壓力,還可以節(jié)約網(wǎng)絡(luò)傳輸?shù)牧髁浚瑫r用戶體驗也更好(用戶打開頁面更快了)。
一般的公司對于靜態(tài)資源以及緩存的處理方式無非就這么幾種:
1、 在靜態(tài)資源后面加一個版本號 v=1.111
2 、 為了準(zhǔn)確的確定文件是否修改,將后面的版本號修改為文件摘要(主要根據(jù)文件內(nèi)容生成的一個值)
以上兩種處理方式,都會存在一些問題。
第一種方式,需要維護(hù)版本號,如果在一個文件中,存在多個資源,那么沒有被修改過的資源文件也會被修改版本號,導(dǎo)致不必要的資源加載。
第二種方式,可以精確的發(fā)現(xiàn)哪一個文件被修改過。從而要求客戶端進(jìn)行重新加載。但是同樣會存在一些問題。
如果先發(fā) html文件:
那么會導(dǎo)致重新加載資源,但一樣還是無法訪問到最新的特性。(畢竟資源文件還沒有真正的更新。),如是Html頁面的結(jié)構(gòu)有更新,但加載了舊的資源,很有可能導(dǎo)致頁面結(jié)構(gòu)的錯亂。并且會緩存資源,直到資源過期,否則除非強(qiáng)制刷新,會一直是錯誤頁面。(這里要注意到,由于第一次加載了舊的資源,版本號又是新的版本號,所以即使在這之后上了資源,這里依舊會讀取舊的資源。
如果先發(fā)資源文件:
如果之前訪問過頁面,那就會有保存有本地緩存,那么由于訪問的還是緩存文件,不會出現(xiàn)問題。但如果是新用戶,那么就會訪問到新的資源文件,很有可能導(dǎo)致頁面錯亂。而等到頁面html也發(fā)布之后,頁面又恢復(fù)了正常。
所以還是建議大家通過nginx來配置靜態(tài)資源緩存過期時間來處理,大概配置如下:
location ~ .*\.(js|css)$ {
expires 30d;
}
三、異步執(zhí)行 (inline)內(nèi)部腳本
inline腳本對性能的影響與外部腳本相比,是有過之而無不及。首先,與外部腳本一樣, inline腳本在執(zhí)行的時候一樣會阻塞并發(fā)請求,除此之外,由于瀏覽器在頁面處理方面是單線程的,當(dāng) inline腳本在頁面渲染之前執(zhí)行時,頁面的渲染工作則會被推遲。簡而言之, inline腳本在執(zhí)行的時候,頁面處于空白狀態(tài)。鑒于以上兩點原因,建議將執(zhí)行時間較長的 inline腳本異步執(zhí)行,異步的方式有很多種,例如使用 script元素的defer 屬性(存在兼容性問題和其他一些問題,例如不能使用 document.write)、使用setTimeout ,此外,在HTML5中引入了 Web Workers的機(jī)制,恰恰可以解決此類問題。
四、(Lazy Load)異步加載 Javascript
隨著 Javascript框架的流行,越來越多的站點也使用起了框架。不過,一個框架往往包括了很多的功能實現(xiàn),這些功能并不是每一個頁面都需要的,如果下載了不需要的腳本則算得上是一種資源浪費 -既浪費了帶寬又浪費了執(zhí)行花費的時間。目前的做法大概有兩種,一種是為那些流量特別大的頁面專門定制一個專用的 mini版框架,另一種則是 Lazy Load。YUI 則使用了第二種方式,在 YUI的實現(xiàn)中,最初只加載核心模塊,其他模塊可以等到需要使用的時候才加載。
五、異步請求 Callback
異步請求 Callback(就是將一些行為樣式提取出來,慢慢的加載信息的內(nèi)容)在某些頁面中可能存在這樣一種需求,需要使用 script標(biāo)簽來異步的請求數(shù)據(jù)。類似:
像以上這種方式直接在頁面上寫 <script>對頁面的性能也是有影響的,即增加了頁面首次加載的負(fù)擔(dān),推遲了 DOMLoaded和window.onload 事件的觸發(fā)時機(jī)。如果時效性允許的話,可以考慮在 DOMLoaded事件觸發(fā)的時候加載,或者使用 setTimeout方式來靈活的控制加載的時機(jī)。
六、減少不必要的 HTTP跳轉(zhuǎn)
對于以目錄形式訪問的 HTTP鏈接,很多人都會忽略鏈接最后是否帶 ’/',假如你的服務(wù)器對此是區(qū)別對待的話,那么你也需要注意,這其中很可能隱藏了 301跳轉(zhuǎn),增加了多余請求。
避免重復(fù)的資源請求
這種情況主要是由于疏忽或頁面由多個模塊拼接而成,然后每個模塊中請求了同樣的資源時,會導(dǎo)致資源的重復(fù)請求
七、減少cookie傳輸
一方面,cookie包含在每次請求和響應(yīng)中,太大的cookie會嚴(yán)重影響數(shù)據(jù)傳輸,因此哪些數(shù)據(jù)需要寫入cookie需要慎重考慮,盡量減少cookie中傳輸?shù)臄?shù)據(jù)量。另一方面,對于某些靜態(tài)資源的訪問,如CSS、script等,發(fā)送cookie沒有意義,可以考慮靜態(tài)資源使用獨立域名訪問,避免請求靜態(tài)資源時發(fā)送cookie,減少cookie傳輸次數(shù)。
八、減少iframe數(shù)量
使用iframe要注意理解iframe的優(yōu)缺點:
▲優(yōu)點
? 可以用來加載速度較慢的內(nèi)容,例如廣告。
? 安全沙箱保護(hù)。瀏覽器會對iframe中的內(nèi)容進(jìn)行安全控制。
? 腳本可以并行下載
▲缺點
? 即使iframe內(nèi)容為空也消耗加載時間
? 會阻止頁面加載
【中杰科技】專注于為客戶提供網(wǎng)站建設(shè)、移動端開發(fā)、微信開發(fā)、系統(tǒng)開發(fā)、電商構(gòu)建等IT技術(shù)服務(wù)