
前言
web端近年來發(fā)展十分迅速,網(wǎng)頁在 native app 中的占比也不斷增加,但H5應(yīng)用的渲染方式,刷新方式與 native 應(yīng)用有很大的區(qū)別。帶來的問題是用戶會感覺刷新慢,易卡頓,體驗差,本篇博文主要針對渲染速度問題進行優(yōu)化~
渲染原理

從上圖可知web界面的渲染原理,這樣我們就可以針對此進行優(yōu)化了,先強調(diào)一下html的加載原理,我們常說的”加載是并行的,執(zhí)行是串行的“的結(jié)果。html開始加載的時候,瀏覽器會將頁面外聯(lián)的css文件和js文件并行加載,如果一個文件還沒回來,它后面的代碼是不會執(zhí)行的。
優(yōu)化渲染速度
大概從如下幾個方面進行優(yōu)化:
- 采用SPA開發(fā)模式
- 采用 Virtual DOM 進行界面更新優(yōu)化
- 服務(wù)端渲染
- 首屏渲染速度優(yōu)化
- 代碼自動化優(yōu)化審查
- 懶加載
- 預(yù)加載
- 資源壓縮
- 開發(fā)規(guī)范
SPA開發(fā)模式
由于傳統(tǒng)多頁模式開發(fā),界面切換造成了頻繁的網(wǎng)絡(luò)請求,導(dǎo)致界面渲染效率十分低下,來自Alexander Aghassipour和Shajith Chacko發(fā)表的這篇文章講述了單頁應(yīng)用程序是如何創(chuàng)建而來的。
單頁面應(yīng)用是指用戶通過瀏覽器加載獨立的HTML頁面并且無需離開此導(dǎo)航頁面,這也是其獨特的優(yōu)勢所在。對用戶操作來說,一旦加載和執(zhí)行單個頁面應(yīng)用程序通常會有更多的響應(yīng),這就需要返回到后端Web服務(wù)器,而單頁面應(yīng)用為用戶提供了更接近一個本地移動或桌面應(yīng)用程序的體驗。
單頁Web應(yīng)用程序的優(yōu)點:
首先,最大的好處是用戶體驗,對于內(nèi)容的改動不需要加載整個頁面。這樣做好處頗多,因為數(shù)據(jù)層和UI的分離,可以重新編寫一個原生的移動設(shè)備應(yīng)用程序而不用(對原有數(shù)據(jù)服務(wù)部分)大動干戈。
單頁面Web應(yīng)用層程序最根本的優(yōu)點是高效。它對服務(wù)器壓力很小,消耗更少的帶寬,能夠與面向服務(wù)的架構(gòu)更好地結(jié)合。
單頁Web應(yīng)用程序的缺點:
雖然還有一些歷史遺留問題(大部分是針對HTML5的改進)以及SEO。如果你看中SEO,那就不應(yīng)該在頁面上使用JavaScript,你應(yīng)該使用網(wǎng)站而不是Web應(yīng)用。目前該技術(shù)還存在一些爭議,但這并不是重點,因為這種類型的體系架構(gòu)為SAAS Web Apps提供了一個極大的可用性。
單頁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ù)對比:
| 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
首先強調(diào)一下,Virtual DOM 并沒有提升首屏渲染速度,而且它還延長了首屏渲染速度,但是 Virtual DOM 提升的是視圖局部更新的速度,能夠依靠映射關(guān)系快速查找到真正的 dom 節(jié)點。
在Virtual DOM方案中,更新瀏覽器的DOM分三個步驟:
- 只要數(shù)據(jù)發(fā)生改變,就會重新生成一個完整的Virtual DOM
- 重新計算比較出新的和之前的Virtual DOM的差異
- 更新真實DOM中真正發(fā)生改變的部分,就像是給DOM打了個補丁
服務(wù)端渲染
稍后補全~
首屏渲染速度優(yōu)化
做移動web頁面,受移動網(wǎng)絡(luò)網(wǎng)速和終端性能影響,我們經(jīng)常要關(guān)注首屏內(nèi)容展示時間(以下簡稱首屏?xí)r間)這個指標(biāo),它衡量著我們的頁面是否能在用戶耐心消磨完之前展示出來,很大程度影響著用戶的使用滿意度。
方案:
- 三秒種渲染完成首屏指標(biāo)
- 首屏加載3秒完成或使用Loading
- 基于聯(lián)通3G網(wǎng)絡(luò)平均338KB/s(2.71Mb/s),所以首屏資源不應(yīng)超過1014KB
- 所有影響首屏加載和渲染的代碼應(yīng)在處理邏輯中后置
按需加載
將不影響首屏的資源和當(dāng)前屏幕資源不用的資源放到用戶需要時才加載,可以大大提升重要資源的顯示速度和降低總體流量
PS:按需加載會導(dǎo)致大量重繪,影響渲染性能
- LazyLoad
- 滾屏加載
- 通過Media Query加載
預(yù)加載
大型重資源頁面(如游戲)可使用增加Loading的方法,資源加載完成后再顯示頁面。但Loading時間過長,會造成用戶流失
對用戶行為分析,可以在當(dāng)前頁加載下一頁資源,提升速度
- 可感知Loading(如進入空間游戲的Loading)
- 不可感知的Loading(如提前加載下一頁)
資源壓縮
減少資源大小可以加快網(wǎng)頁顯示速度,所以要對HTML、CSS、JavaScript等進行代碼壓縮,并在服務(wù)器端設(shè)置GZip
- 壓縮(例如,多余的空格、換行符和縮進)
- 啟用GZip
- 控制圖片質(zhì)量(使用 tinypng 進行壓縮)
開發(fā)建議
html注意事項
加載是并行的:
- 別再把 JsEndTime – JsStartTime 的結(jié)果成為js文件的加載執(zhí)行時間(除非你沒有外聯(lián)css文件),不然會被內(nèi)行人取笑滴;
- css文件的阻塞會影響后面js代碼的執(zhí)行,自然也包括html代碼的執(zhí)行,即是說此時你的頁面就是空白的。所以css文件盡量內(nèi)聯(lián),你可以讓構(gòu)建工具幫你忙;
執(zhí)行是串行的:
- 無關(guān)緊要”的js不要放在負責(zé)渲染的js前面,這里的“無關(guān)緊要”是指和首屏渲染無關(guān),如數(shù)據(jù)上報組件。我們可以選擇將要上報的數(shù)據(jù)臨時存起來,先繼續(xù)執(zhí)行渲染的js,等負責(zé)渲染的js執(zhí)行完再加載上報組件再上報。甚至連zepto之類的庫我們也可以放后面,把渲染相關(guān)的代碼抽離出來并用原生js書寫,放到最前面
- 可以看到,動態(tài)加載的js的執(zhí)行是不會受到html后面外聯(lián)的js的阻塞的影響,即是說,它的執(zhí)行和后面js的執(zhí)行順序是不確定的。因此我們要小心處理好文件的依賴關(guān)系。當(dāng)然還可以采用最不容易出錯的方法:負責(zé)動態(tài)加載js的文件是html里面外聯(lián)的最后一個文件
html使用Viewport
Viewport可以加速頁面的渲染,請使用以下代碼
<meta name="viewport" content="width=device-width, initial-scale=1">
減少Dom節(jié)點
Dom節(jié)點太多影響頁面的渲染,應(yīng)盡量減少Dom節(jié)點
減少HTTP請求
因為手機瀏覽器同時響應(yīng)請求為4個請求(Android支持4個,iOS 5后可支持6個),所以要盡量減少頁面的請求數(shù),首次加載同時請求數(shù)不能超過4個
- 合并CSS、JavaScript
- 合并小圖片,使用雪碧圖
無阻塞
寫在HTML頭部的JavaScript(無異步),和寫在HTML標(biāo)簽中的Style會阻塞頁面的渲染,因此CSS放在頁面頭部并使用Link方式引入,避免在HTML標(biāo)簽中寫Style,JavaScript放在頁面尾部或使用異步方式加載
減少Cookie
Cookie會影響加載速度,所以靜態(tài)資源域名不使用Cookie
避免重定向
重定向會影響加載速度,所以在服務(wù)器正確設(shè)置避免重定向
異步加載第三方資源
第三方資源不可控會影響頁面的加載和顯示,因此要異步加載第三方資源
腳本執(zhí)行優(yōu)化
- CSS寫在頭部,JavaScript寫在尾部或異步
- 避免圖片和iFrame等的空Src(空Src會重新加載當(dāng)前頁面,影響速度和效率)
- 盡量避免重設(shè)圖片大?。ㄖ卦O(shè)圖片大小是指在頁面、CSS、JavaScript等中多次重置圖片大小,多次重設(shè)圖片大小會引發(fā)圖片的多次重繪,影響性能)
- 圖片盡量避免使用DataURL(DataURL圖片沒有使用圖片的壓縮算法文件會變大,并且要解碼后再渲染,加載慢耗時長)