網(wǎng)絡(luò)加載類
1. 減少HTTP資源請(qǐng)求次數(shù)
在前端頁(yè)面中,通常建議盡可能合并靜態(tài)資源圖片、JavaScript和CSS代碼,減少頁(yè)面請(qǐng)求數(shù)和資源請(qǐng)求消耗,這樣可以縮短頁(yè)面首次訪問(wèn)的用戶等待時(shí)間。通過(guò)構(gòu)建工具合并雪碧圖、CSS、JavaScript文件等都是為了減少HTTP資源請(qǐng)求次數(shù)。另外也要盡量避免重復(fù)的資源,防止增加多余請(qǐng)求。
2. 減小HTTP請(qǐng)求大小
除了減少HTTP資源請(qǐng)求次數(shù),也要盡量減小每個(gè)HTTP請(qǐng)求的大小。如減少?zèng)]必要的圖片、JavaScript、CSS及HTML代碼,對(duì)文件進(jìn)行壓縮優(yōu)化,或者使用gzip壓縮傳輸內(nèi)容等都可以用來(lái)減小文件大小,縮短網(wǎng)絡(luò)傳輸?shù)却龝r(shí)延。
3. 將CSS或JavaScript放到外部文件中,避免使用<style>或<script>標(biāo)簽直接引入
在HTML文件中引用外部資源可以有效利用瀏覽器的靜態(tài)資源緩存,但有時(shí)候在移動(dòng)端頁(yè)面CSS或JavaScript比較簡(jiǎn)單的情況下為了減少請(qǐng)求,也會(huì)將CSS或JavaScript直接寫到HTML里面,具體要根據(jù)CSS或JavaScript文件的大小和業(yè)務(wù)的場(chǎng)景來(lái)分析。如果CSS或JavaScript文件內(nèi)容較多,業(yè)務(wù)邏輯較復(fù)雜,建議放到外部文件引入。
4. 避免頁(yè)面中空的href和src
當(dāng)<link>標(biāo)簽的href屬性為空,或<script>、<img>、<iframe>標(biāo)簽的src屬性為空時(shí),瀏覽器在渲染的過(guò)程中仍會(huì)將href屬性或src屬性中的空內(nèi)容進(jìn)行加載,直至加載失敗,這樣就阻塞了頁(yè)面中其他資源的下載進(jìn)程,而且最終加載到的內(nèi)容是無(wú)效的,因此要盡量避免。
5. 為HTML指定Cache-Control或Expires
為HTML內(nèi)容設(shè)置Cache-Control或Expires可以將HTML內(nèi)容緩存起來(lái),避免頻繁向服務(wù)器端發(fā)送請(qǐng)求。在頁(yè)面Cache-Control或Expires頭部有效時(shí),瀏覽器將直接從緩存中讀取內(nèi)容,不向服務(wù)器端發(fā)送請(qǐng)求。
<meta http-equiv="Cache-Control" content="max-age=7200">
<meta http-equiv="Expires" content="Mon,20Jul201623:00:00GMT">
6. 合理設(shè)置Etag和Last-Modified
合理設(shè)置Etag和Last-Modified使用瀏覽器緩存,對(duì)于未修改的文件,靜態(tài)資源服務(wù)器會(huì)向?yàn)g覽器端返回304,讓瀏覽器從緩存中讀取文件,減少Web資源下載的帶寬消耗并降低服務(wù)器負(fù)載。
<meta http-equiv="last-modified" content="Sun,05 Nov 2017 13:45:57 GMT">
7. 減少頁(yè)面重定向
頁(yè)面每次重定向都會(huì)延長(zhǎng)頁(yè)面內(nèi)容返回的等待延時(shí),一次重定向大約需要200毫秒不等的時(shí)間開銷(無(wú)緩存),為了保證用戶盡快看到頁(yè)面內(nèi)容,要盡量避免頁(yè)面重定向。
8. 使用靜態(tài)資源分域存放來(lái)增加下載并行數(shù)
瀏覽器在同一時(shí)刻向同一個(gè)域名請(qǐng)求文件的并行下載數(shù)是有限的,因此可以利用多個(gè)域名的主機(jī)來(lái)存放不同的靜態(tài)資源,增大頁(yè)面加載時(shí)資源的并行下載數(shù),縮短頁(yè)面資源加載的時(shí)間。通常根據(jù)多個(gè)域名來(lái)分別存儲(chǔ)JavaScript、CSS和圖片文件。
<link rel="stylesheet" >
<script src="http://cdn2.domain.com/path/main.js"></script>
9. 使用靜態(tài)資源CDN來(lái)存儲(chǔ)文件
如果條件允許,可以利用CDN網(wǎng)絡(luò)加快同一個(gè)地理區(qū)域內(nèi)重復(fù)靜態(tài)資源文件的響應(yīng)下載速度,縮短資源請(qǐng)求時(shí)間。
10. 使用CDN Combo下載傳輸內(nèi)容
CDN Combo是在CDN服務(wù)器端將多個(gè)文件請(qǐng)求打包成一個(gè)文件的形式來(lái)返回的技術(shù),這樣可以實(shí)現(xiàn)HTTP連接傳輸?shù)囊淮涡詮?fù)用,減少瀏覽器的HTTP請(qǐng)求數(shù),加快資源下載速度。例如同一個(gè)域名CDN服務(wù)器上的a.js,b.js,c.js就可以按如下方式在一個(gè)請(qǐng)求中下載。
<script src="http://cdn.domain.com/path/a.js,b.js,c.js"></script>
11. 使用可緩存的AJAX
對(duì)于返回內(nèi)容相同的請(qǐng)求,沒(méi)必要每次都直接從服務(wù)端拉取,合理使用AJAX緩存能加快AJAX響應(yīng)速度并減輕服務(wù)器壓力。
$.ajax({
url : url,
type : 'get',
cache : true, //推薦使用緩存
data : {},
success (){//...},
error (){//...}
});
12. 使用GET來(lái)完成AJAX請(qǐng)求
使用XMLHttpRequest時(shí),瀏覽器中的POST方法會(huì)發(fā)起兩次TCP數(shù)據(jù)包傳輸,首先發(fā)送文件頭,然后發(fā)送HTTP正文數(shù)據(jù)。而使用GET時(shí)只發(fā)送頭部,所以在拉取服務(wù)端數(shù)據(jù)時(shí)使用GET請(qǐng)求效率更高。
$.ajax({
url : url,
type : 'get', //推薦使用get完成請(qǐng)求
data : {},
success (){//...},
error(){//...}
});
13. 減少Cookie的大小并進(jìn)行Cookie隔離
HTTP請(qǐng)求通常默認(rèn)帶上瀏覽器端的Cookie一起發(fā)送給服務(wù)器,所以在非必要的情況下,要盡量減少Cookie來(lái)減小HTTP請(qǐng)求的大小。對(duì)于靜態(tài)資源,盡量使用不同的域名來(lái)存放,因?yàn)镃ookie默認(rèn)是不能跨域的,這樣就做到了不同域名下靜態(tài)資源請(qǐng)求的Cookie隔離。
14. 縮小favicon.ico并緩存
有利于favicon.ico的重復(fù)加載,因?yàn)橐话阋粋€(gè)Web應(yīng)用的favicon.ico是很少改變的。
15. 推薦使用異步JavaScript資源
異步的JavaScript資源不會(huì)阻塞文檔解析,所以允許在瀏覽器中優(yōu)先渲染頁(yè)面,延后加載腳本執(zhí)行。例如JavaScript的引用可以如下設(shè)置,也可以使用模塊化加載機(jī)制來(lái)實(shí)現(xiàn)。
<script src="main.js" defer></script>
<script src="main.js" async></script>
使用async時(shí),加載和渲染后續(xù)文檔元素的過(guò)程和main.js的加載與執(zhí)行是并行的。使用defer時(shí),加載后續(xù)文檔元素的過(guò)程和main.js的加載是并行的,但是main.js的執(zhí)行要在頁(yè)面所有元素解析完成之后才開始執(zhí)行。
16. 消除阻塞渲染的CSS及JavaScript
對(duì)于頁(yè)面中加載時(shí)間過(guò)長(zhǎng)的CSS或JavaScript文件,需要進(jìn)行合理拆分或延后加載,保證關(guān)鍵路徑的資源能快速加載完成。
17. 避免使用CSS import引用加載CSS
CSS中的@import可以從另一個(gè)樣式文件中引入樣式,但應(yīng)該避免這種用法,因?yàn)檫@樣會(huì)增加 CSS 資源加載的關(guān)鍵路徑長(zhǎng)度,帶有@import的CSS樣式需要在CSS文件串行解析到@import時(shí)才會(huì)加載另外的CSS文件,大大延后CSS渲染完成的時(shí)間。
<!--不推薦-->
<style>
@import "path/main.css";
</style>
<!--推薦-->
<link rel="stylesheet" >
18. meta dns prefetch設(shè)置DNS預(yù)解析
設(shè)置文件資源的DNS預(yù)解析,讓瀏覽器提前解析獲取靜態(tài)資源的主機(jī)IP,避免等到請(qǐng)求時(shí)才發(fā)起DNS解析請(qǐng)求。通常在移動(dòng)端HTML中可以采用如下方式完成。
<!--cdn域名預(yù)解析-->
<meta http-equiv="x-dns-prefetch-control" content="on" >
<link rel="dns-prefetch" >
19. 資源預(yù)加載
對(duì)于移動(dòng)端首屏加載后可能會(huì)被使用的資源,需要在首屏完成加載后盡快進(jìn)行加載,保證在用戶需要瀏覽時(shí)已經(jīng)加載完成,這時(shí)候如果再去異步請(qǐng)求就顯得很慢。
20. 首屏加載和按需加載,非首屏內(nèi)容滾屏加載,保證首屏內(nèi)容最小化
由于移動(dòng)端網(wǎng)絡(luò)速度相對(duì)較慢,網(wǎng)絡(luò)資源有限,因此為了盡快完成頁(yè)面內(nèi)容的加載,需要保證首屏加載資源最小化,非首屏內(nèi)容使用滾動(dòng)的方式異步加載。一般推薦移動(dòng)端頁(yè)面首屏數(shù)據(jù)展示延時(shí)最長(zhǎng)不超過(guò)3秒。推薦首屏所有資源大小不超過(guò) 1014KB,即大約不超過(guò) 1MB。
頁(yè)面渲染類
1. 把CSS資源引用放到HTML文件頂部
一般推薦將所有CSS資源盡早指定在HTML文檔<head>中,這樣瀏覽器可以優(yōu)先下載CSS并盡早完成頁(yè)面渲染。
2. JavaScript資源引用放到HTML文件底部
JavaScript資源放到HTML文檔底部可以防止JavaScript的加載和解析執(zhí)行對(duì)頁(yè)面渲染造成阻塞。由于JavaScript資源默認(rèn)是解析阻塞的,除非被標(biāo)記為異步或者通過(guò)其他的異步方式加載,否則會(huì)阻塞HTML DOM解析和CSS渲染的過(guò)程。
3. 盡量預(yù)先設(shè)定圖片等大小
在加載大量的圖片元素時(shí),盡量預(yù)先限定圖片的尺寸大小,否則在圖片加載過(guò)程中會(huì)更新圖片的排版信息,產(chǎn)生大量的重排
4. 不要在HTML中直接縮放圖片
在HTML中直接縮放圖片會(huì)導(dǎo)致頁(yè)面內(nèi)容的重排重繪,此時(shí)可能會(huì)使頁(yè)面中的其他操作產(chǎn)生卡頓,因此要盡量減少在頁(yè)面中直接進(jìn)行圖片縮放。
5. 減少DOM元素?cái)?shù)量和深度
HTML中標(biāo)簽元素越多,標(biāo)簽的層級(jí)越深,瀏覽器解析DOM并繪制到瀏覽器中所花的時(shí)間就越長(zhǎng),所以應(yīng)盡可能保持DOM元素簡(jiǎn)潔和層級(jí)較少。
<!--不推薦-->
<div>
<span>
<a href="javascript:void(0);">
<img src="./path/photo.jpg" alt="圖片">
</a>
</span>
</div>
<!--推薦-->
<img src="./path/photo.jpg" alt="圖片" >
6. 盡量避免在選擇器末尾添加通配符
CSS解析匹配到渲染樹的過(guò)程是從右到左的逆向匹配,在選擇器末尾添加通配符至少會(huì)增加一倍多計(jì)算量。
7. 減少使用關(guān)系型樣式表的寫法
直接使用唯一的類名即可最大限度的提升渲染引擎繪制渲染樹等效率
8. 盡量減少使用JS動(dòng)畫
JS直接操作DOM極容易引起頁(yè)面的重排
9. CSS 動(dòng)畫使用translate、scale代替top、height
盡量使用CSS3的translate、scale屬性代替top、left和height、width,避免大量的重排計(jì)算
10. 盡量避免使用<table>、<iframe>
<table>內(nèi)容的渲染是將table的DOM渲染樹全部生成完并一次性繪制到頁(yè)面上的,所以在長(zhǎng)表格渲染時(shí)很耗性能,應(yīng)該盡量避免使用它,可以考慮使用列表元素<ul>代替。盡量使用異步的方式動(dòng)態(tài)添加iframe,因?yàn)?code>iframe內(nèi)資源的下載進(jìn)程會(huì)阻塞父頁(yè)面靜態(tài)資源的下載與CSS及HTML DOM的解析。
11. 避免運(yùn)行耗時(shí)的JavaScript
長(zhǎng)時(shí)間運(yùn)行的JavaScript會(huì)阻塞瀏覽器構(gòu)建DOM樹、DOM渲染樹、渲染頁(yè)面。所以,任何與頁(yè)面初次渲染無(wú)關(guān)的邏輯功能都應(yīng)該延遲加載執(zhí)行,這和JavaScript資源的異步加載思路是一致的。
12. 避免使用CSS表達(dá)式或CSS濾鏡
CSS表達(dá)式或CSS濾鏡的解析渲染速度是比較慢的,在有其他解決方案的情況下應(yīng)該盡量避免使用。
//不推薦
.opacity{
filter : progid : DXImageTransform.Microsoft.Alpha( opacity = 50 );
}
13. 使用Viewport固定屏幕渲染,可以加速頁(yè)面渲染內(nèi)容
一般認(rèn)為,在移動(dòng)端設(shè)置Viewport可以加速頁(yè)面的渲染,同時(shí)可以避免縮放導(dǎo)致頁(yè)面重排重繪。在移動(dòng)端固定Viewport設(shè)置的方法如下。
<!--設(shè)置viewport不縮放-->
<meta name="viewport" content="width=device-width,initial-scale=1.0,maximum-scale=1.0,user-scalable=no">
14. 避免各種形式重排重繪
頁(yè)面的重排重繪很耗性能,所以一定要盡可能減少頁(yè)面的重排重繪,例如頁(yè)面圖片大小變化、元素位置變化等這些情況都會(huì)導(dǎo)致重排重繪。
15. 使用CSS3動(dòng)畫,開啟GPU加速
使用CSS3動(dòng)畫時(shí)可以設(shè)置transform:translateZ(0)來(lái)開啟移動(dòng)設(shè)備瀏覽器的GPU圖形處理加速,讓動(dòng)畫過(guò)程更加流暢,但需要注意的是,在Native WebView下GPU加速有幾率產(chǎn)生 App Crash。
-webkit-transform:translateZ(0);
-ms-transform:translateZ(0);
-o-transform:translateZ(0);
transform:translateZ(0);
16. 合理使用Canvas和requestAnimationFrame
選擇Canvas或requestAnimationFrame等更高效的動(dòng)畫實(shí)現(xiàn)方式,盡量避免使用setTimeout、setInterval等方式來(lái)直接處理連續(xù)動(dòng)畫。
17. SVG代替圖片
部分情況下可以考慮使用SVG代替圖片實(shí)現(xiàn)動(dòng)畫,因?yàn)槭褂肧VG格式內(nèi)容更小,而且SVG DOM結(jié)構(gòu)方便調(diào)整。
6. 不濫用float
在DOM渲染樹生成后的布局渲染階段,使用float的元素布局計(jì)算比較耗性能,所以盡量減少float的使用,推薦使用固定布局或flex-box彈性布局的方式來(lái)實(shí)現(xiàn)頁(yè)面元素布局。
18. 不濫用web字體或過(guò)多font-size
聲明過(guò)多的font-size聲明會(huì)增加字體的大小計(jì)算,而且也沒(méi)有必要的。
19. 做好腳本容錯(cuò)
腳本容錯(cuò)可以避免「非正常環(huán)境」的執(zhí)行錯(cuò)誤影響頁(yè)面的加載和不相關(guān)功能的使用。
圖片類
1. 圖片壓縮處理
在移動(dòng)端,通常要保證頁(yè)面中一切用到的圖片都是經(jīng)過(guò)壓縮優(yōu)化處理的,而不是以原圖的形式直接使用的,因?yàn)槟菢雍芟牧髁浚壹虞d時(shí)間更長(zhǎng)。
2. 使用較小的圖片
合理使用base64內(nèi)嵌圖片在頁(yè)面使用的背景圖片不多且較小的情況下,可以將圖片轉(zhuǎn)化成base64編碼嵌入到HTML頁(yè)面或CSS文件中,這樣可以減少頁(yè)面的HTTP請(qǐng)求數(shù)。需要注意的是,要保證圖片較小,一般圖片大小超過(guò)2KB就不推薦使用base64嵌入顯示了。
.class-name{
background-image : url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAALCAMAAABxsOwqAAAAYFBMVEWnxwusyQukxQudwQyZvgyhxAyfwgyxzAsUHQGOuA0aJAERGAFIXwSTugyEqgtqhghQZgUwQQIpOQKbuguVtQuKrAuCowp2kQlheghTbQZHWQU7SwVAVgQ6TgQlLwMeKwFOemyQAAAAVElEQVQI1y3JVRaAIAAF0UconXbvf5ei8HfPDIQQhBAAFE10iKig3SLRNN4SP/p+N08VC0YnfIlNWtqIkhg/TPYbCvhqdHAWRXPZSp3g3CWZvVLXC6OJA3ukv0AaAAAAAElFTkSuQmCC');
}
3. 使用更高壓縮比格式的圖片
使用具有較高壓縮比格式的圖片,如webp(需要設(shè)計(jì)降級(jí)兼容方案)等。在同等圖片畫質(zhì)的情況下,高壓縮比格式的圖片體積更小,能夠更快完成文件傳輸,節(jié)省網(wǎng)絡(luò)流量。
<img src="http://cdn.domain.com/path/photo.webp" alt="webp格式圖片" >
4. 圖片懶加載
為了保證頁(yè)面內(nèi)容的最小化,加速頁(yè)面的渲染,盡可能節(jié)省移動(dòng)端網(wǎng)絡(luò)流量,頁(yè)面中的圖片資源推薦使用懶加載實(shí)現(xiàn),在頁(yè)面滾動(dòng)時(shí)動(dòng)態(tài)載入圖片。
<img data-src="http://cdn.domain.com/path/photo.jpg" alt="懶加載圖片" >
5. 使用MediaQuery或srcset根據(jù)不同屏幕加載不同大小圖片
針對(duì)不同的移動(dòng)端屏幕尺寸和分辨率,輸出不同大小的圖片或背景圖能保證在用戶體驗(yàn)不降低的前提下節(jié)省網(wǎng)絡(luò)流量,加快部分機(jī)型的圖片加載速度,這在移動(dòng)端非常值得推薦。
6. 使用iconfont代替圖片圖標(biāo)
在頁(yè)面中盡可能使用iconfont來(lái)代替圖片圖標(biāo),這樣做的好處有以下幾個(gè):
- 使用
iconfont體積較小,而且是矢量圖,因此縮放時(shí)不會(huì)失真; - 可以方便地修改圖片大小尺寸和呈現(xiàn)顏色。
但是需要注意的是,iconfont引用不同webfont格式時(shí)的兼容性寫法,根據(jù)經(jīng)驗(yàn)推薦盡量按照以下順序書寫,否則不容易兼容到所有的瀏覽器上。
@font-face{
font-family:iconfont;
src:url("./iconfont.eot");
src:url("./iconfont.eot?#iefix") format("eot"),
url("./iconfont.woff") format("woff"),
url("./iconfont.ttf") format("truetype");
}
7. 定義圖片大小限制
加載的單張圖片一般建議不超過(guò)30KB,避免大圖片加載時(shí)間長(zhǎng)而阻塞頁(yè)面其他資源的下載,因此推薦在10KB以內(nèi)。如果用戶上傳的圖片過(guò)大,建議設(shè)置告警系統(tǒng),幫助我們觀察了解整個(gè)網(wǎng)站的圖片流量情況,做出進(jìn)一步的改善。
8. 強(qiáng)緩存策略
對(duì)于一些「永遠(yuǎn)」不會(huì)變的圖片可以使用強(qiáng)緩存的方式緩存在用戶的瀏覽器上。
架構(gòu)協(xié)議類
1. 使用后端數(shù)據(jù)渲染
使用后端數(shù)據(jù)渲染的方式可以加快頁(yè)面內(nèi)容的渲染展示,避免空白頁(yè)面的出現(xiàn),同時(shí)可以解決移動(dòng)端頁(yè)面SEO的問(wèn)題。如果條件允許,后端數(shù)據(jù)渲染是一個(gè)很不錯(cuò)的實(shí)踐思路。