這只是小程序用戶體驗優(yōu)化的一個小小案例,優(yōu)化方案也需要根據(jù)各位讀者自己的實(shí)際情況具體問題具體分析。
0x00 源起
這張動圖展示的是我們正式發(fā)布的小程序“相生一課”點(diǎn)擊課程列表項進(jìn)入課程詳情頁的加載過程。從點(diǎn)擊跳轉(zhuǎn)到最終顯示出頁面需要 5-6 秒時間。這簡直令人發(fā)指有沒有?大 boss 發(fā)話了,用戶體驗第一位,必須立刻、馬上改掉。
嗯,于是我們馬上開始排查。
0x01 排查步驟
由于小程序的開發(fā)基本是參照官方文檔進(jìn)行操作的,到目前為止也沒有什么第三方工具,前端導(dǎo)致瓶頸的可能性被我們暫時排除了。所以我們的第一懷疑目標(biāo)就到了網(wǎng)絡(luò)接口上。
1. 接口數(shù)據(jù)排查
小程序上需要獲取到服務(wù)器數(shù)據(jù)以后再進(jìn)行視圖的填充和渲染,網(wǎng)絡(luò)請求接口返回數(shù)據(jù)過慢,會導(dǎo)致從跳轉(zhuǎn)到頁面顯示的過程變慢。
在微信 web 開發(fā)工具中打開調(diào)試頁面,查看 network 標(biāo)簽頁。我們發(fā)現(xiàn)這個頁面共請求了 6 個接口(下圖中前兩個接口是其他頁面的),其中有 2 個返回的數(shù)據(jù)量比較大,耗時也比較長。
- 課程章節(jié)列表,返回 12.7KB 數(shù)據(jù),耗時 834ms。
- 課程詳情內(nèi)容,返回 10.2KB 數(shù)據(jù),耗時 332 ms。
接口確實(shí)很慢。
這兩個接口都返回了 10KB 以上的數(shù)據(jù),需要考慮減少數(shù)據(jù)返回。
課程詳情內(nèi)容
現(xiàn)在課程詳情內(nèi)容確實(shí)比較多,這需要從內(nèi)容運(yùn)營人員那邊入手,技術(shù)上暫時無法調(diào)整了。
課程章節(jié)列表
我們發(fā)現(xiàn)服務(wù)端接口本身似乎是支持分頁的,但是現(xiàn)在小程序是一次性獲取了所有的課程章節(jié)數(shù)據(jù)。解決方案有了:調(diào)整產(chǎn)品的交互方式,章節(jié)列表分頁加載,可以滑動到底部加載更多,減少每次接口請求獲取的數(shù)據(jù)量,加快接口返回。
2. 業(yè)務(wù)代碼排查
接口上發(fā)現(xiàn)了部分問題,可是不對呀。從點(diǎn)擊到頁面顯示等待了 5-6 秒。所有接口就算串行請求也不過 2 秒多,一定還有其他原因。
于是,我們開始檢查小程序上的代碼實(shí)現(xiàn)。
檢查接口的請求處理邏輯
進(jìn)入這個頁面發(fā)起了 6 個接口請求,如果請求不是以異步的形式發(fā)起,那么在同步請求的情況下,所有數(shù)據(jù)的獲取時間會是每個接口返回的時間疊加。如果沒有在請求數(shù)據(jù)返回時就顯示相應(yīng)的視圖,而是所有數(shù)據(jù)都返回時才更新頁面。這兩點(diǎn)都會造成界面顯示出來的時間過長,是用戶覺得慢。
以異步形式發(fā)起請求
小程序官方提供的網(wǎng)絡(luò)請求 API 本身是以異步形式執(zhí)行請求的。大部分小程序開發(fā)者應(yīng)該是以這種方式裸跑的。
我們對其進(jìn)行了簡單封轉(zhuǎn),每個請求返回 Promise 對象,這樣代碼書寫上多個請求可以組合。書寫上確實(shí)方便了,但錯誤使用對導(dǎo)致打包在一起的請求中,返回時間最長的那個會成為瓶頸。
經(jīng)排查,這 6 個接口是分開異步請求的。
一個接口返回數(shù)據(jù)以后就處理其相應(yīng)的視圖邏輯
前端視圖是需要數(shù)據(jù)進(jìn)行渲染的,相關(guān)性強(qiáng)的數(shù)據(jù)可以歸到一組。這是接口設(shè)計的依據(jù)之一,一組數(shù)據(jù)通過一個接口返回。
從產(chǎn)品設(shè)計上看,課程基礎(chǔ)數(shù)據(jù)、課程詳情內(nèi)容、課程章節(jié)列表是這個頁面最主要的數(shù)據(jù),并且這 3 塊數(shù)據(jù)在視圖上有明顯的區(qū)分。
- 頁面頂部顯示的是課程基礎(chǔ)數(shù)據(jù)。數(shù)據(jù)量少,接口很快就返回了。
- 課程詳情占用一塊獨(dú)立的區(qū)域,在第一屏可以看得到。數(shù)據(jù)量比較大,接口返回耗時。
- 課程章節(jié)列表占用一塊獨(dú)立的區(qū)域,在第一屏看不到。數(shù)據(jù)量比較大,接口返回耗時。
我們可以在課程基礎(chǔ)數(shù)據(jù)返回時先顯示課程的基礎(chǔ)數(shù)據(jù);接著課程詳情返回時再顯示課程詳情;但滑動到課程章節(jié)區(qū)域時,在進(jìn)行加載并顯示。
通過產(chǎn)品設(shè)計上的改進(jìn),極大縮短了用戶看到頁面內(nèi)容的時間。
然后我去倒了杯水,繼續(xù)...
3. 更進(jìn)一步
進(jìn)入課程詳情頁面的時間確實(shí)加快了,但是優(yōu)先顯示了課程基礎(chǔ)信息,課程詳情的加載還是非常地慢,并且大大超出了接口返回時間。更嚴(yán)重的是,課程詳情加載過程中,點(diǎn)擊頁面上的按鈕暫時沒有響應(yīng)。知道課程詳情加載完,才出現(xiàn)按鈕點(diǎn)擊的響應(yīng)。
這說明主線程發(fā)生了阻塞。請求都是異步發(fā)起的,莫非請求返回以后的處理出現(xiàn)了阻塞?我們定位到了這兩行代碼:
var weappDetail = getApp().httpReplace(weapp_detail);
WxParse.wxParse('article', 'html', weappDetail, self, 5);
課程詳情內(nèi)容是富文本格式的,小程序上使用第三方 WxParse 組件進(jìn)行渲染,在小城官方?jīng)]有出 <rich-text /> 組件前一直是富文本解析與顯示的首選方案。經(jīng)測試這行代碼的處理耗時近 3 秒。
罪魁禍?zhǔn)渍业搅?,我們考慮很多方法來優(yōu)化,最后打算換官方 <rich-text /> 來試一下。沒想到這一試就停不下來了。
直接上效果圖:
是不是如絲般順滑?我們也一下子變得自信起來!
<rich-text /> 使用注意事項:
-
<img />標(biāo)簽顯示的圖片是原圖大小,可能超出屏幕顯示區(qū)域。這個為<img />加上 style 就可以解決了。 - 暫時不支持
<video />等標(biāo)簽。這從產(chǎn)品、內(nèi)容上考慮解決方案。 -
<rich-text />是基礎(chǔ)庫 1.4.0 以后開始支持的,需要做低版本的兼容。 -
<rich-text />中的圖片無法單獨(dú)點(diǎn)擊放大查看。
目前就這些,其他問題也請讀者進(jìn)行反饋。
WxParse之所以這么慢,可能是因為我們要渲染的富文本內(nèi)容太多了,并且其中有大量圖片。少量富文本內(nèi)容時還是可以的。
0x02 總結(jié)
這篇文章中發(fā)現(xiàn)的小程序加載慢的原因有:
- 網(wǎng)絡(luò)接口返回數(shù)據(jù)慢
- 接口響應(yīng)慢
- 數(shù)據(jù)傳輸量過大
- 多個接口沒有異步獲取數(shù)據(jù)
- 網(wǎng)絡(luò)接口數(shù)據(jù)返回后沒有在合理時機(jī)更新視圖
- 數(shù)據(jù)解析慢
相應(yīng)的解決方案:
- 優(yōu)化接口反應(yīng)速度
- 減少接口返回數(shù)據(jù)量
- 列表數(shù)據(jù)分頁加載
- 產(chǎn)品設(shè)計上減少必須內(nèi)容
- 分成多個接口
- 編碼時使用異步方式請求接口
- 優(yōu)化產(chǎn)品的顯示邏輯,做相應(yīng)編碼調(diào)整
- 使用合適的富文本組件
0x03 寫在最后
以上提到的產(chǎn)品用戶體驗的優(yōu)化,技術(shù)層面可以提升,產(chǎn)品設(shè)計層面也可以提升。作為技術(shù)人雖然可能比較擅長從技術(shù)層面出發(fā),對于產(chǎn)品層面也是應(yīng)該學(xué)習(xí)和思考的。
如果你看完本文有收獲,歡迎關(guān)注微信公眾號:非典型程序員(ID:up2048),更多技術(shù)干貨等你一起學(xué)習(xí)與交流。
- EOF -