前言
web端近年來發(fā)展十分迅速,網(wǎng)頁在 native app 中的占比也不斷增加褒搔,但H5應(yīng)用的渲染方式阶牍,刷新方式與 native 應(yīng)用有很大的區(qū)別。帶來的問題是用戶會(huì)感覺刷新慢星瘾,易卡頓走孽,體驗(yàn)差,本篇博文主要針對(duì)渲染速度問題進(jìn)行優(yōu)化~
渲染原理
從上圖可知web界面的渲染原理死相,這樣我們就可以針對(duì)此進(jìn)行優(yōu)化了融求,先強(qiáng)調(diào)一下html的加載原理,我們常說的”加載是并行的算撮,執(zhí)行是串行的“的結(jié)果生宛。html開始加載的時(shí)候,瀏覽器會(huì)將頁面外聯(lián)的css文件和js文件并行加載肮柜,如果一個(gè)文件還沒回來陷舅,它后面的代碼是不會(huì)執(zhí)行的。
優(yōu)化渲染速度
大概從如下幾個(gè)方面進(jìn)行優(yōu)化:
- 采用SPA開發(fā)模式
- 采用 Virtual DOM 進(jìn)行界面更新優(yōu)化
- 服務(wù)端渲染
- 首屏渲染速度優(yōu)化
- 代碼自動(dòng)化優(yōu)化審查
- 懶加載
- 預(yù)加載
- 資源壓縮
- 開發(fā)規(guī)范
SPA開發(fā)模式
由于傳統(tǒng)多頁模式開發(fā)审洞,界面切換造成了頻繁的網(wǎng)絡(luò)請(qǐng)求莱睁,導(dǎo)致界面渲染效率十分低下待讳,來自Alexander Aghassipour和Shajith Chacko發(fā)表的這篇文章講述了單頁應(yīng)用程序是如何創(chuàng)建而來的。
單頁面應(yīng)用是指用戶通過瀏覽器加載獨(dú)立的HTML頁面并且無需離開此導(dǎo)航頁面仰剿,這也是其獨(dú)特的優(yōu)勢所在创淡。對(duì)用戶操作來說,一旦加載和執(zhí)行單個(gè)頁面應(yīng)用程序通常會(huì)有更多的響應(yīng)南吮,這就需要返回到后端Web服務(wù)器琳彩,而單頁面應(yīng)用為用戶提供了更接近一個(gè)本地移動(dòng)或桌面應(yīng)用程序的體驗(yàn)。
單頁Web應(yīng)用程序的優(yōu)點(diǎn):
首先部凑,最大的好處是用戶體驗(yàn)露乏,對(duì)于內(nèi)容的改動(dòng)不需要加載整個(gè)頁面。這樣做好處頗多涂邀,因?yàn)閿?shù)據(jù)層和UI的分離瘟仿,可以重新編寫一個(gè)原生的移動(dòng)設(shè)備應(yīng)用程序而不用(對(duì)原有數(shù)據(jù)服務(wù)部分)大動(dòng)干戈。
單頁面Web應(yīng)用層程序最根本的優(yōu)點(diǎn)是高效比勉。它對(duì)服務(wù)器壓力很小劳较,消耗更少的帶寬,能夠與面向服務(wù)的架構(gòu)更好地結(jié)合浩聋。
單頁Web應(yīng)用程序的缺點(diǎn):
雖然還有一些歷史遺留問題(大部分是針對(duì)HTML5的改進(jìn))以及SEO兴想。如果你看中SEO,那就不應(yīng)該在頁面上使用JavaScript赡勘,你應(yīng)該使用網(wǎng)站而不是Web應(yīng)用。目前該技術(shù)還存在一些爭議捞镰,但這并不是重點(diǎn)闸与,因?yàn)檫@種類型的體系架構(gòu)為SAAS Web Apps提供了一個(gè)極大的可用性。
單頁Web應(yīng)用程序的結(jié)構(gòu)很簡單:首先傳遞HTML文檔框架岸售;然后使用JavaScript修改頁面践樱;緊接著再從服務(wù)器傳遞更多數(shù)據(jù)然后再修改頁面,如此循環(huán)凸丸。從性能的角度看拷邢,在現(xiàn)代瀏覽器中單頁面Web App已經(jīng)能夠和普通應(yīng)用程序相媲美,而且?guī)缀跛械牟僮飨到y(tǒng)都支持現(xiàn)代的瀏覽器屎慢。使用HTML+CSS+Javascript編寫應(yīng)用程序瞭稼,能使更多的人們都加入到程序開發(fā)的行列。
在單頁開發(fā)框架中腻惠,我建議使用vue 2环肘,下圖是一些關(guān)于界面渲染相關(guān)的數(shù)據(jù)對(duì)比:
Type | Vue 2(單位/s) | React 15(單位/s) | Angular 2(單位/s) |
---|---|---|---|
create rows Duration for creating 1000 rows after the page loaded. | 171.36 | 227.44 | 198.06 |
replace all rows Duration for updating all 1000 rows of the table (with 5 warmup iterations) | 68.76 | 211.71 | 178.45 |
remove row Duration to remove a row. (with 5 warmup iterations). | 64.11 | 49.42 | 19.14 |
partial update Time to update the text of every 10th row (with 5 warmup iterations) | 22.17 | 14.77 | 11.42 |
ready memory Memory usage after page load | 3.43 | 4.64 | 15.45 |
Virtual DOM
首先強(qiáng)調(diào)一下,Virtual DOM 并沒有提升首屏渲染速度集灌,而且它還延長了首屏渲染速度悔雹,但是 Virtual DOM 提升的是視圖局部更新的速度,能夠依靠映射關(guān)系快速查找到真正的 dom 節(jié)點(diǎn)。
在Virtual DOM方案中腌零,更新瀏覽器的DOM分三個(gè)步驟:
- 只要數(shù)據(jù)發(fā)生改變梯找,就會(huì)重新生成一個(gè)完整的Virtual DOM
- 重新計(jì)算比較出新的和之前的Virtual DOM的差異
- 更新真實(shí)DOM中真正發(fā)生改變的部分,就像是給DOM打了個(gè)補(bǔ)丁
服務(wù)端渲染
稍后補(bǔ)全~
首屏渲染速度優(yōu)化
做移動(dòng)web頁面益涧,受移動(dòng)網(wǎng)絡(luò)網(wǎng)速和終端性能影響锈锤,我們經(jīng)常要關(guān)注首屏內(nèi)容展示時(shí)間(以下簡稱首屏?xí)r間)這個(gè)指標(biāo),它衡量著我們的頁面是否能在用戶耐心消磨完之前展示出來饰躲,很大程度影響著用戶的使用滿意度牙咏。
方案:
- 三秒種渲染完成首屏指標(biāo)
- 首屏加載3秒完成或使用Loading
- 基于聯(lián)通3G網(wǎng)絡(luò)平均338KB/s(2.71Mb/s),所以首屏資源不應(yīng)超過1014KB
- 所有影響首屏加載和渲染的代碼應(yīng)在處理邏輯中后置
按需加載
將不影響首屏的資源和當(dāng)前屏幕資源不用的資源放到用戶需要時(shí)才加載嘹裂,可以大大提升重要資源的顯示速度和降低總體流量
PS:按需加載會(huì)導(dǎo)致大量重繪妄壶,影響渲染性能
- LazyLoad
- 滾屏加載
- 通過Media Query加載
預(yù)加載
大型重資源頁面(如游戲)可使用增加Loading的方法,資源加載完成后再顯示頁面寄狼。但Loading時(shí)間過長丁寄,會(huì)造成用戶流失
對(duì)用戶行為分析,可以在當(dāng)前頁加載下一頁資源泊愧,提升速度
- 可感知Loading(如進(jìn)入空間游戲的Loading)
- 不可感知的Loading(如提前加載下一頁)
資源壓縮
減少資源大小可以加快網(wǎng)頁顯示速度伊磺,所以要對(duì)HTML、CSS删咱、JavaScript等進(jìn)行代碼壓縮屑埋,并在服務(wù)器端設(shè)置GZip
- 壓縮(例如,多余的空格痰滋、換行符和縮進(jìn))
- 啟用GZip
- 控制圖片質(zhì)量(使用 tinypng 進(jìn)行壓縮)
開發(fā)建議
html注意事項(xiàng)
加載是并行的:
- 別再把 JsEndTime – JsStartTime 的結(jié)果成為js文件的加載執(zhí)行時(shí)間(除非你沒有外聯(lián)css文件)摘能,不然會(huì)被內(nèi)行人取笑滴;
- css文件的阻塞會(huì)影響后面js代碼的執(zhí)行敲街,自然也包括html代碼的執(zhí)行团搞,即是說此時(shí)你的頁面就是空白的。所以css文件盡量內(nèi)聯(lián)多艇,你可以讓構(gòu)建工具幫你忙逻恐;
執(zhí)行是串行的:
- 無關(guān)緊要”的js不要放在負(fù)責(zé)渲染的js前面,這里的“無關(guān)緊要”是指和首屏渲染無關(guān)峻黍,如數(shù)據(jù)上報(bào)組件复隆。我們可以選擇將要上報(bào)的數(shù)據(jù)臨時(shí)存起來,先繼續(xù)執(zhí)行渲染的js奸披,等負(fù)責(zé)渲染的js執(zhí)行完再加載上報(bào)組件再上報(bào)昏名。甚至連zepto之類的庫我們也可以放后面,把渲染相關(guān)的代碼抽離出來并用原生js書寫阵面,放到最前面
- 可以看到轻局,動(dòng)態(tài)加載的js的執(zhí)行是不會(huì)受到html后面外聯(lián)的js的阻塞的影響洪鸭,即是說,它的執(zhí)行和后面js的執(zhí)行順序是不確定的仑扑。因此我們要小心處理好文件的依賴關(guān)系览爵。當(dāng)然還可以采用最不容易出錯(cuò)的方法:負(fù)責(zé)動(dòng)態(tài)加載js的文件是html里面外聯(lián)的最后一個(gè)文件
html使用Viewport
Viewport可以加速頁面的渲染,請(qǐng)使用以下代碼
<meta name="viewport" content="width=device-width, initial-scale=1">
減少Dom節(jié)點(diǎn)
Dom節(jié)點(diǎn)太多影響頁面的渲染镇饮,應(yīng)盡量減少Dom節(jié)點(diǎn)
減少HTTP請(qǐng)求
因?yàn)槭謾C(jī)瀏覽器同時(shí)響應(yīng)請(qǐng)求為4個(gè)請(qǐng)求(Android支持4個(gè)蜓竹,iOS 5后可支持6個(gè)),所以要盡量減少頁面的請(qǐng)求數(shù)储藐,首次加載同時(shí)請(qǐng)求數(shù)不能超過4個(gè)
- 合并CSS俱济、JavaScript
- 合并小圖片,使用雪碧圖
無阻塞
寫在HTML頭部的JavaScript(無異步)钙勃,和寫在HTML標(biāo)簽中的Style會(huì)阻塞頁面的渲染蛛碌,因此CSS放在頁面頭部并使用Link方式引入,避免在HTML標(biāo)簽中寫Style辖源,JavaScript放在頁面尾部或使用異步方式加載
減少Cookie
Cookie會(huì)影響加載速度蔚携,所以靜態(tài)資源域名不使用Cookie
避免重定向
重定向會(huì)影響加載速度,所以在服務(wù)器正確設(shè)置避免重定向
異步加載第三方資源
第三方資源不可控會(huì)影響頁面的加載和顯示克饶,因此要異步加載第三方資源
腳本執(zhí)行優(yōu)化
- CSS寫在頭部酝蜒,JavaScript寫在尾部或異步
- 避免圖片和iFrame等的空Src(空Src會(huì)重新加載當(dāng)前頁面,影響速度和效率)
- 盡量避免重設(shè)圖片大蟹取(重設(shè)圖片大小是指在頁面亡脑、CSS、JavaScript等中多次重置圖片大小邀跃,多次重設(shè)圖片大小會(huì)引發(fā)圖片的多次重繪远豺,影響性能)
- 圖片盡量避免使用DataURL(DataURL圖片沒有使用圖片的壓縮算法文件會(huì)變大,并且要解碼后再渲染坞嘀,加載慢耗時(shí)長)