WEB前端性能优化总结——如何提高网页加载速度
一、提高網(wǎng)頁加載速度的必要性
國際知名的一組來自Jupiter Research的數(shù)據(jù)顯示:購物者在訪問網(wǎng)站過程中的不滿會(huì)導(dǎo)致銷售損失和品牌受損,其中 77%的人將不再訪問網(wǎng)站 ,62%的人不再從該網(wǎng)站上購買,48%會(huì)轉(zhuǎn)向競(jìng)爭(zhēng)對(duì)手,28%的人對(duì)公司產(chǎn)生負(fù)面印象。
此組數(shù)據(jù)分析顯示:Google網(wǎng)站訪問速度每慢400 ms就將導(dǎo)致用戶搜索請(qǐng)求下降 0.59%;Amazon表示,增加 100ms的網(wǎng)站延遲將導(dǎo)致其收入下降 1%;雅虎網(wǎng)站如果有400ms 延遲會(huì)導(dǎo)致流量下降 5-9%…
大數(shù)據(jù)分析表明:當(dāng)網(wǎng)站首頁打開時(shí)間超過4秒時(shí),約60%的用戶會(huì)放棄繼續(xù)訪問瀏覽,83%的用戶希望首頁打開時(shí)間不要超過4秒。
據(jù)調(diào)查發(fā)現(xiàn),影響用戶體驗(yàn)的因素有很多,如購物方便性、網(wǎng)站合理布局等,但最重要的是網(wǎng)站性能和網(wǎng)站可用性能,這兩項(xiàng)對(duì)用戶的影響占到了69%。
結(jié)語:網(wǎng)站網(wǎng)頁加載速度越慢,用戶體驗(yàn)度就越低,將導(dǎo)致網(wǎng)站擁有者的收益大幅減少。因此,提高網(wǎng)頁加載速度就成了前端工程師的必修課之一。
二、前端性能優(yōu)化
網(wǎng)頁加載順序:1.DNS查找 > 2.下載并渲染HTML文件 > 3.下載并執(zhí)行css及js組件 > 4.下載圖片
以下性能優(yōu)化列表,按照對(duì)網(wǎng)頁加載速度的提升幅度排序
DNS查找,即瀏覽器根據(jù)url中域名,查找該域名對(duì)應(yīng)的服務(wù)器IP地址,然后才能根據(jù)服務(wù)器IP地址,下載到文件。在DNS查找完成之前,所有的文件下載都無法執(zhí)行。每一次DNS查找時(shí)間約20-120ms。
一般而言,電腦會(huì)進(jìn)行DNS緩存,包括瀏覽器緩存、系統(tǒng)緩存、路由器緩存、ISP DNS緩存。所以,瀏覽器DNS查找順序一般是這樣的:瀏覽器緩存→系統(tǒng)緩存→路由器緩存→ISP DNS 緩存→遞歸搜索。
遞歸搜索,即ISP的DNS服務(wù)器從根域名開始進(jìn)行遞歸查詢,查找時(shí)間一般為20-120ms。
若沒有DNS緩存,才會(huì)執(zhí)行DNS遞歸搜索。但是顯而易見,第一次訪問網(wǎng)站首頁時(shí),是不會(huì)有DNS緩存的,必然會(huì)執(zhí)行DNS查找。而每一個(gè)DNS查找,需要耗時(shí)20-120ms。因此,減少DNS查找能加快網(wǎng)頁加載速度。
實(shí)例:
在開發(fā)頁面時(shí),很多時(shí)候,我們都要用到別人已經(jīng)封裝好了的js及css文件,譬如jquery庫、angularjs庫、時(shí)間選擇插件、定位插件等等諸多插件,一般而言,網(wǎng)上都有公用的CDN,我們不需要將這些文件下載到本地,就可以使用它們。
譬如:w3c上推薦了谷歌的CDN,騰訊地圖也有自己的CDN庫,我們可以通過以下代碼,獲取到谷歌的jquery庫,以及騰訊的前端定位插件。
這樣寫做起來十分方便,我們可以省去下載文件這一步驟。但實(shí)際上,這樣做會(huì)增加兩個(gè)DNS查找,即"ajax.googleapis.com"和"3gimg.qq.com"的DNS查找,將會(huì)在首次加載網(wǎng)站首頁時(shí),拖慢首頁加載速度40-240ms,而且每再增加一個(gè)DNS查找,還會(huì)額外拖慢20-120ms的加載時(shí)間,這是極為致命的。
不僅如此,這兩個(gè)文件的下載速度分別取決于谷歌服務(wù)器及騰訊服務(wù)器的下載速度,這是完全不可控的。而將自己網(wǎng)站所需要的文件,寄放在別人的服務(wù)器上,也是不安全的。例如,某一天谷歌的服務(wù)器抽風(fēng),無法再下載文件,或是谷歌不再支持該jquery庫,那么我們的網(wǎng)站將會(huì)失去jquery核心庫,會(huì)直接崩潰。更可怕的是,若谷歌在該jquery庫文件中添加某些攻擊性手段,將會(huì)直接導(dǎo)致網(wǎng)站處于危險(xiǎn)狀態(tài)中。
因此,為了減少DNS查找,為了保障網(wǎng)站的安全,我們必須將網(wǎng)站所需的文件下載到本地,而不是調(diào)用別人支持的CDN。
2. CSS優(yōu)先加載,JS延遲加載
在解析HTML文件,構(gòu)建DOM樹時(shí),一旦遇到link標(biāo)記時(shí),即遇到了CSS樣式表,將之下載,便可立即構(gòu)建渲染樹,從而立即呈現(xiàn)頁面效果。
而一旦遇到script 標(biāo)記時(shí),即遇到了JS腳本,將立即阻塞DOM樹的構(gòu)建,將控制權(quán)移交給 JavaScript 引擎,等到 JavaScript 引擎運(yùn)行完畢,瀏覽器才會(huì)從中斷的地方恢復(fù)渲染樹的構(gòu)建。這涉及到瀏覽器渲染原理,詳情請(qǐng)見本人上一篇博客:瀏覽器渲染頁面的原理及流程
若將引入JS腳本的鏈接放到HTML頁面頂部,那么在加載該頁面時(shí),一旦遇到JS,頁面渲染就會(huì)停滯,出現(xiàn)一段時(shí)間的灰色空白,直到JS加載完成,才會(huì)出現(xiàn)頁面內(nèi)容,這對(duì)用戶體驗(yàn)是不友好的。因此,我們需要將JS腳本放置到頁面底部,或者讓JS腳本異步或是延遲加載。
實(shí)例:如下圖所示,該首頁有CSS樣式表一個(gè),若將CSS樣式表置于JS腳本之下,那么在加載完JS腳本之前,頁面都不會(huì)進(jìn)行渲染,會(huì)出現(xiàn)108ms的灰色空白。該首頁有JS腳本文件5個(gè),若將這5個(gè)JS文件放置在該首頁的頂部,那么該首頁加載JS腳本時(shí),也將會(huì)出現(xiàn)108ms的灰色空白。
從嚴(yán)格意義上來說,CSS的優(yōu)先加載及JS的延遲加載并不能從根本上提升網(wǎng)頁加載速度,但是它們能使網(wǎng)頁更快被渲染出來,使頁面內(nèi)容逐步呈現(xiàn),增加用戶等待的耐心,提升用戶體驗(yàn)。
3. 減少HTTP請(qǐng)求
HTTP請(qǐng)求,即客戶端到服務(wù)器端的請(qǐng)求消息,包括資源請(qǐng)求、數(shù)據(jù)處理等。
HTTP請(qǐng)求需從客戶端發(fā)起請(qǐng)求,然后由服務(wù)器端進(jìn)行數(shù)據(jù)處理,然后再返回?cái)?shù)據(jù)或資源。一般而言,耗時(shí)據(jù)請(qǐng)求資源的大小,服務(wù)器網(wǎng)速,約數(shù)ms-數(shù)百ms之間。請(qǐng)求資源越大,所花費(fèi)的時(shí)間越長,服務(wù)器網(wǎng)速越慢,所花費(fèi)的時(shí)間也越長。
一般而言,完成了DNS查找后,接下來便是進(jìn)行HTTP請(qǐng)求,獲取資源。首先下載HTML文件,然后解析HTML文件,根據(jù)HTML內(nèi)容,獲取CSS、JS及圖片文件。每一個(gè)CSS鏈接、JS鏈接以及圖片鏈接都是一個(gè)HTTP請(qǐng)求。
每一個(gè)HTTP請(qǐng)求都需要花費(fèi)額外的時(shí)間。因此,我們可以將一些可合并的資源進(jìn)行合并,譬如將所有頁面的css合并成一個(gè)style.css文件,譬如將所有頁面的js合并成一個(gè)function.js文件,再譬如將一批小圖標(biāo)利用ps合成一張圖片(此手段效果最顯著,也最常用)。雖然有時(shí)文件會(huì)變大,但是在HTTP請(qǐng)求中,請(qǐng)求下載一個(gè)大小為100KB的資源文件,比請(qǐng)求下載兩個(gè)大小為50KB的資源文件要快。
從實(shí)際測(cè)試來看,每減少一個(gè)HTTP請(qǐng)求,據(jù)請(qǐng)求資源大小,能加快網(wǎng)頁加載速度約數(shù)ms-數(shù)百ms。
實(shí)例:合并圖標(biāo)
"用戶信息頁面"如下圖所示:四個(gè)輸入框左側(cè),有四張icon,合計(jì)大小8.9KB,四個(gè)HTTP請(qǐng)求合計(jì)時(shí)間23ms。
我利用ps,將此四張圖片進(jìn)行合并,然后以css的背景圖片進(jìn)行引用,其結(jié)果如下圖所示:四個(gè)輸入框左側(cè),四張icon合并后的大小6.0KB,一個(gè)HTTP請(qǐng)求時(shí)間8ms。減小圖片大小2.9KB,提升加載速度15ms。看起來提升速度不多,但按比例算,提升幅度巨大。
4. 縮小文件
眾所周知,HTTP請(qǐng)求中,返回的資源越大,HTTP請(qǐng)求所花費(fèi)的時(shí)間越長,因此,縮小資源文件可以提升HTTP請(qǐng)求的速度,進(jìn)而提升頁面加載速度。不僅如此,還能節(jié)省服務(wù)器流量及空間。
一般而言,縮小文件主要是指圖片壓縮,也包括CSS、JS文件壓縮,網(wǎng)上有成熟的代碼在線壓縮工具,譬如:在線JS/CSS/HTML 壓縮
而圖片壓縮主要是指圖片在不同的格式下、不同的分辨率下保存,其大小將會(huì)有巨大的差異。譬如同一張圖片的png格式與jpg格式肉眼看起來幾乎沒有區(qū)別,但是其大小相差了約5倍。而jpg格式中級(jí)也比高級(jí)要小約莫1倍。當(dāng)然,圖片的不同格式有不同的用處,且分辨率越高,圖片也越清晰。
因此,根據(jù)需求為圖片選擇合適的格式及分辨率,就能得到最小的圖片文件。
具體操作:在ps中打開圖片,同時(shí)按下ctrl+alt+shift+s,打開"存儲(chǔ)為web所用格式"彈框,即可任意選擇保存圖片的格式及分辨率(若按操作無法順利壓縮圖片,請(qǐng)自行度娘)。
實(shí)例:同一張圖片,jpg格式比png格式小約5倍,加載速度快約3倍。
縮小文件來提升頁面加載速度,從我個(gè)人的項(xiàng)目優(yōu)化經(jīng)驗(yàn)來看,其效果極為顯著,多個(gè)項(xiàng)目都提升了超過100ms的加載時(shí)間。
5. 善于利用緩存
避免在HTML文件中使用style標(biāo)簽插入CSS樣式,及使用script標(biāo)簽插入JS腳本。若在HTML文件中插入CSS及JS,那么它們無法進(jìn)入緩存,每次刷新頁面,都要重新加載,不但浪費(fèi)了瀏覽器資源,拖慢了頁面加載速度,而且顯得冗余且復(fù)用性低,不利于日后的維護(hù)。因此,將CSS樣式與JS腳本分離出來,形成CSS文件及JS文件,就能進(jìn)入緩存,進(jìn)而提高頁面加載速度。
靈活使用cookie和localstorage。在使用接口時(shí),靈活使用cookie和localstorage來緩存接口返回的信息,避免不必要的接口查詢,從而提升頁面加載速度。譬如:在登錄頁面登錄時(shí),緩存好用戶信息,設(shè)置過期時(shí)間。在進(jìn)入用戶個(gè)人中心頁面時(shí),若數(shù)據(jù)并未過期,可以直接從緩存中取用戶信息,不必再調(diào)起接口去獲取用戶信息。
實(shí)例:css、js、圖片都可進(jìn)行緩存,從緩存中獲取文件,時(shí)間為0ms。
總結(jié):以上幾點(diǎn),對(duì)于頁面加載速度的提升效果都很顯著,只要做到以上幾點(diǎn),只要服務(wù)器不坑,項(xiàng)目頁面加載速度都不會(huì)很慢。以下我將會(huì)從代碼的角度來提出幾點(diǎn)項(xiàng)目優(yōu)化的經(jīng)驗(yàn)。
6. HTML文件代碼優(yōu)化
1. 避免使用空請(qǐng)求,包括空的href鏈接、空src鏈接。空鏈接本身無法請(qǐng)求成功,因此會(huì)把一個(gè)HTTP請(qǐng)求拖到超時(shí),而且空鏈接會(huì)阻塞頁面中其他資源的下載進(jìn)程,會(huì)拖慢頁面加載速度。譬如:。
2. 根據(jù)項(xiàng)目大小,選擇主要使用class還是id。id選擇器優(yōu)先級(jí)最高,訪問速度最快。但是在html中每聲明一個(gè)id,就會(huì)在JS底層聲明一個(gè)全局變量,而全局變量的增多,將會(huì)拖慢JS中變量遍歷的效率,若變量遍歷達(dá)到十萬次以上,就會(huì)出現(xiàn)較顯著的延遲,而且容易造成全局變量污染。對(duì)于小項(xiàng)目,并無影響,但是對(duì)中大型項(xiàng)目來說,尤其是游戲項(xiàng)目,影響很大。個(gè)人推薦,當(dāng)項(xiàng)目較小時(shí),靈活使用class和id,當(dāng)項(xiàng)目較大時(shí),盡量少使用id。
3. 預(yù)先設(shè)定圖片大小。在頁面加載過程中,圖片最后加載,若不對(duì)圖片預(yù)設(shè)大小,當(dāng)圖片加載完成后,將會(huì)引起大量的重排,將會(huì)浪費(fèi)瀏覽器資源及拖慢頁面加載速度。
4. 盡量減少DOM元素的數(shù)量與層級(jí)。解析HTML時(shí),標(biāo)簽的數(shù)量越多,標(biāo)簽的層級(jí)越深,瀏覽器解析構(gòu)建DOM樹的時(shí)間就越長,應(yīng)盡可能的減少DOM元素的數(shù)量和層級(jí)。
5. 盡量避免使用table標(biāo)簽。瀏覽器對(duì)table標(biāo)簽的解析是全部生成后再一次性繪制的,因此會(huì)造成表格位置較長時(shí)間的空白,推薦使用ul及l(fā)i標(biāo)簽繪制表格。
6. 使用異步加載iframe標(biāo)簽。瀏覽器加載iframe標(biāo)簽時(shí),會(huì)阻塞父頁面渲染樹的構(gòu)建及HTTP請(qǐng)求,因此盡量使用異步加載iframe。
等等…
7. CSS樣式代碼優(yōu)化
1. 禁止使用樣式表達(dá)式。CSS表達(dá)式從IE5起開始支持,但僅有IE支持。它的解析速度較慢,而且運(yùn)算次數(shù)遠(yuǎn)比我們想象的要大,隨意動(dòng)動(dòng)鼠標(biāo)就能輕松達(dá)到上萬次運(yùn)算,會(huì)對(duì)頁面性能造成影響。譬如:"#myDiv{width:expression(document.body.offsetWidth - 110 + “px”); }"
2. 優(yōu)化關(guān)鍵選擇器,去掉無效的父級(jí)選擇器,盡量少在選擇器末尾使用通配符。大多數(shù)人都認(rèn)為,瀏覽器對(duì)CSS選擇器的解析式從左往右進(jìn)行的,譬如選擇器:"#myDiv ul li a",大多數(shù)人會(huì)認(rèn)為這個(gè)選擇器效率極高,畢竟第一個(gè)ID #myDiv 就已經(jīng)把范圍限定了,先選擇 #myDiv ,再在 #myDiv 下尋找 ul ,再一級(jí)一級(jí)往下,直到找到 a 標(biāo)簽,效率很高。事實(shí)上這是錯(cuò)的,瀏覽器對(duì)CSS選擇器的解析式從右往左進(jìn)行的。在上述選擇器中,瀏覽器會(huì)先去尋找 a 標(biāo)簽,范圍為全局,再在 a 標(biāo)簽的列表中,尋找父級(jí)標(biāo)簽是 li 標(biāo)簽的 a 標(biāo)簽,一直向上,直到最后,找到父級(jí)標(biāo)簽是 #myDiv ul li 的a標(biāo)簽。因此,效率并不像想象中那么高。顯而易見,"#myDi a"選擇器比"#myDiv ul li a"選擇器效率要高得多。而通配符 a 的效率遠(yuǎn)比類選擇器及id選擇器低,若給 a 標(biāo)簽添加一個(gè)class myA ,構(gòu)造新選擇器:"#myDiv .myA",它的效率又遠(yuǎn)比"#myDi a"要高了。瀏覽器對(duì)CSS選擇器的解析式從右往左進(jìn)行,因此在選擇器末尾最好使用類選擇器,而不是通配符。CSS選擇器效率問題詳情請(qǐng)見:CSS選擇器效率問題
等等…
8. JS代碼優(yōu)化
1. ajax請(qǐng)求方法按需求選擇get或是post,訪問接口所花費(fèi)的時(shí)間在頁面加載時(shí)間中占很大的比重,而接口訪問方法中,get方法遠(yuǎn)比post方法要快,因此按需選擇接口訪問方法很重要。
2. 減少全局變量,盡量使用局部變量。js中,全局變量運(yùn)算速率遠(yuǎn)低于局部變量,速度差異達(dá)到上百倍,且全局變量越多,全局變量的查找速率便越慢。詳情請(qǐng)見:減少全局變量對(duì)效率的提升
3. 減少對(duì)DOM的操作。js操作DOM將會(huì)引起頁面的重繪及重排,需要花費(fèi)時(shí)間及耗費(fèi)瀏覽器資源。
等等…
結(jié)語:前端性能優(yōu)化是一門完整的學(xué)問,并非一兩篇博客所能詳盡的。以上我只是按照頁面加載速度的提升幅度寫了幾點(diǎn),其實(shí)還有大量優(yōu)化手段,難以詳盡。譬如:圖片懶加載、按需加載、預(yù)加載等等,再譬如:從網(wǎng)絡(luò)加載角度進(jìn)行優(yōu)化、從渲染角度進(jìn)行優(yōu)化、從架構(gòu)協(xié)議角度進(jìn)行優(yōu)化等等
學(xué)無止境,諸君共勉!
總結(jié)
以上是生活随笔為你收集整理的WEB前端性能优化总结——如何提高网页加载速度的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 爬虫前面
- 下一篇: 2017年html5行业报告,云适配发布