前語(yǔ):
最近一向在做功用優(yōu)化和模塊化改造的作業(yè),并完結(jié)了一次前端重構(gòu)。在這里總結(jié)出一些經(jīng)歷和得失來幫助咱們思考。共兩篇文章,第一篇評(píng)論功用優(yōu)化,第二篇評(píng)論模塊化結(jié)構(gòu)。而之所以把這兩個(gè)論題放到一同,是由于這兩項(xiàng)作業(yè)都涉及到對(duì)前端代碼進(jìn)行不一樣程度的重構(gòu),并且模塊化改造其實(shí)是咱們?cè)趯?duì)功用優(yōu)化做到必定程度以后發(fā)現(xiàn)有必要要做的一件事情。本篇是功用優(yōu)化的有些,下面我把咱們的商品簡(jiǎn)稱為N頁(yè)面。
應(yīng)用場(chǎng)景剖析:
N頁(yè)面作為一個(gè)進(jìn)口頁(yè)面,對(duì)頁(yè)面加載速度有著極高的請(qǐng)求。一起,N頁(yè)面內(nèi)部卻又有著非常復(fù)雜的功用與交互。N頁(yè)面的第一版上線時(shí),頁(yè)面引用的js文件有3個(gè),總共40-50k(緊縮&Gzip以后)。頁(yè)面onload時(shí)刻在1.3秒。
1.3秒的load時(shí)刻,相比較絕大多數(shù)網(wǎng)站來說都是一個(gè)不錯(cuò)的數(shù)值。但老板一句話“怎樣這個(gè)頁(yè)面翻開這么慢”,馬上像是給咱們的后背安了一枚定時(shí)炸彈。功用優(yōu)化成了N頁(yè)面下一步作業(yè)的重中之重。
老板注重頁(yè)面速度,關(guān)于Web前端開發(fā)人員來說其實(shí)是件幸事,這表明你將有更豐厚的時(shí)刻和資本去實(shí)習(xí)Web功用優(yōu)化這一課題,不必被輾轉(zhuǎn)反側(cè)的商品升級(jí)需要所打擾。那么關(guān)于N頁(yè)面,咱們做了哪些實(shí)習(xí):
常規(guī)優(yōu)化手法包含:
CSS置頂,JS置底。
靜態(tài)資本外聯(lián)、兼并、緊縮。
圖像優(yōu)化。(Png運(yùn)用pngcrush;Gif運(yùn)用gifsicle;Jpeg運(yùn)用jpegtran)
圖像推遲加載。(首要對(duì)于首屏外的圖像。)
運(yùn)用CSS Sprite,首屏圖像悉數(shù)合到一張圖上。
靜態(tài)文件上CDN。(靜態(tài)文件的下載能提速20%左右。)
靜態(tài)文件設(shè)置強(qiáng)緩存。(射中強(qiáng)緩存82.4%;射中若緩存3.4%;未射中緩存14.2%。)
HTML緊縮。(Gzip后削減%5。)
增強(qiáng)型手法:
根底庫(kù)定制。(用代碼剖析代碼,主動(dòng)打包被運(yùn)用到的辦法作為根底庫(kù),使根底庫(kù)從本來的緊縮后25K減小為9.8K,減小了61%)
頁(yè)面數(shù)據(jù)存儲(chǔ)優(yōu)化。(從本來的直接寫json形式的script,變?yōu)閷son隱藏在textarea中,初始化或用到的時(shí)分才去獲取并進(jìn)行解析。)
首屏CSS檢測(cè)。(對(duì)首屏用到的CSS進(jìn)行檢測(cè),將不歸于首屏的CSS代碼獨(dú)自打包并移到首屏以外進(jìn)行推遲加載)
js按需加載。(在后面做要點(diǎn)介紹)
監(jiān)控& 丈量
功用優(yōu)化最重要的作業(yè)不是優(yōu)化而是監(jiān)控。這個(gè)道理很簡(jiǎn)單:沒有監(jiān)控系統(tǒng)就沒辦法衡量功用優(yōu)化的作用,那么你所做的任何作業(yè)都是盲目的。
咱們對(duì)功用的監(jiān)控是從多個(gè)維度展開的,包含均勻時(shí)刻、時(shí)段散布、瀏覽器散布、省份、運(yùn)營(yíng)商等。便于發(fā)現(xiàn)和定位任何一個(gè)細(xì)節(jié)的疑問。
而在均勻時(shí)刻這一維度,咱們又分為四個(gè)等級(jí):
1.Head時(shí)刻– head標(biāo)簽加載完結(jié)的時(shí)刻
2.TTi時(shí)刻– 頁(yè)面可交互時(shí)刻(即首屏第一次烘托出來的時(shí)刻)
3.Dom時(shí)刻– Dom Ready的時(shí)刻
4.Load 時(shí)刻– 頁(yè)面徹底加載完結(jié)的時(shí)刻
這么區(qū)分的優(yōu)點(diǎn)是,頁(yè)面加載每個(gè)環(huán)節(jié)的耗時(shí)一望而知:
Head :CSS加載時(shí)刻
TTI :全體HTML加載和烘托時(shí)刻
DOM 減TTI : js文件網(wǎng)絡(luò)傳輸時(shí)刻和在瀏覽器進(jìn)行解析的時(shí)刻
Load 減Dom : js初始化+ 圖像加載的時(shí)刻
并且,咱們經(jīng)過移動(dòng)tti時(shí)刻點(diǎn)的方位,發(fā)現(xiàn)了一個(gè)風(fēng)趣的景象,如下圖
能夠看出,頁(yè)面加載的功用瓶頸就在script的下載和解析時(shí)刻。
為了進(jìn)一步定位功用瓶頸,咱們?cè)陧?yè)面內(nèi)對(duì)用戶網(wǎng)速進(jìn)行了測(cè)驗(yàn),結(jié)果很震動(dòng):有2%的用戶網(wǎng)速小于2k/s,5%的用戶網(wǎng)速小于10k/s。(國(guó)內(nèi)的網(wǎng)絡(luò)狀況真是不忍目睹。
那么,優(yōu)化計(jì)劃就很顯著了:最大極限地減小js文件巨細(xì),以減小網(wǎng)絡(luò)傳輸時(shí)刻,提升頁(yè)面功用。
經(jīng)過后來的優(yōu)化作業(yè)咱們發(fā)現(xiàn):js代碼緊縮、Gzip后每減小1k,頁(yè)面加載時(shí)刻就能減小10ms左右。
按需加載:
這是除了js緊縮外,你能想到的最有用減小js文件巨細(xì)的辦法了。
按需加載,望文生義,即是在頁(yè)面初次加載的時(shí)分只提供最需要的js給用戶,而剩下的js等用戶運(yùn)用到了有關(guān)的功用再去加載。
按需加載合適哪種類型的網(wǎng)站:假如80%的用戶來到你的頁(yè)面只運(yùn)用20%的功用,那么就有必要把這20%的js作為首屏加載,而剩下的js做按需加載。
從這個(gè)視點(diǎn)來講,幾乎一切網(wǎng)站都能夠做按需加載,由于總有一些功用是用戶很少會(huì)用到的。
那么,如何做按需加載:
按需加載需要有一套js模塊加載的結(jié)構(gòu)。這個(gè)結(jié)構(gòu)的作用是:確保在所需的js加載完結(jié)后才去履行回調(diào)辦法。
按需加載還需要有一套觸發(fā)條件。在咱們的頁(yè)面中,對(duì)鼠標(biāo)移動(dòng)和鼠標(biāo)點(diǎn)擊都進(jìn)行了監(jiān)聽,以確保在用戶想運(yùn)用某個(gè)功用之前或進(jìn)行了相應(yīng)操作時(shí),觸發(fā)js加載。
除此以外,咱們還對(duì)js根底庫(kù)進(jìn)行了進(jìn)一步拆分,分為首屏用到的根底辦法,和推遲加載的js所需的根底辦法。以最大極限地確保首屏js量的最小化。
經(jīng)過按需加載的拆分,咱們將首屏的js代碼從本來的gzip以后40-50k減小到了只有24k。
一起,咱們對(duì)CSS的加載也進(jìn)行拆分,首屏不需要的CSS代碼也隨JS進(jìn)行推遲加載。
作用 & 總結(jié)
功用優(yōu)化是一個(gè)非常繁瑣的作業(yè),頁(yè)面功用受許多要素的制約,不過相信一點(diǎn):辦法總比疑問多。咱們經(jīng)過優(yōu)化,最終將頁(yè)面加載時(shí)刻降到了650ms,僅為優(yōu)化前的一半。一切優(yōu)化作業(yè)中,作用最顯著的即是js按需加載了。
|