本文首發於公衆號:符合預期的CoyPan
性能優化是前端開發中不可避免的一個話題。本文將記錄一次客戶端內H5頁面首屏性能優化的項目。css
信息流App是當下最流行的產品之一,現在日頭條等。我所在的團隊也是在作這樣一款信息流App。App的Feed流是客戶端Native實現的。用戶點擊Feed流中的文章後,會進入到文章底層頁。文章底層頁大部分都是Native實現的,可是有一些文章的數據是非結構化的,Native沒有辦法很好地處理,因此用H5頁面來承接這部分文章。整個業務場景很簡單,用圖表示以下:
html
毫無疑問,H5頁面會極大影響App的用戶體驗。所以,H5頁面的首屏性能是十分重要的,要爭取能作到秒開。前端
優化前,H5底層頁的加載流程以下:webpack
上圖的加載流程是一個很常見的頁面加載流程。在這個流程中,至少包含了四次http請求。每一次http都會拖慢頁面呈現的時間。若是是一個單獨的H5頁面,沒有任何問題,可是這個頁面是在客戶端內,是要爭取作到秒開的。ios
服務端渲染。服務端渲染是將數據請求和頁面結構生成放到服務端完成,用戶訪問頁面url時,接口吐出的就是完整的,帶有數據內容的html,首屏速度天然會有提高。可是這裏有幾個問題:golang
一、目前的非結構化文章數據就是一大串HTML字符串,服務端不太好去處理一大串HTML的字符串。web
二、就算實施了ssr,在用戶訪問H5底層頁連接的時候,始終會有一次Http請求,首屏速度依然會收到網絡環境等因素的影響。性能優化
一個完整的離線包方案,是根據業務模塊配置,把H5頁面和相關資源都打包上傳,而後客戶端在特定的時機對離線包進行預下載,解壓、檢驗等工做,而後在特定的時機使用離線包裏的本地文件等。離線包是一個不錯的解決方案,可是離線包有一個問題:過重了。網絡
權衡了各類因素後,咱們採用了下面的解決方案:性能
總結起來,就是後臺提供預加載接口,準備好H5底層頁須要的Html,文章數據,js,css等,用戶點擊進入到底層頁時,客戶端直接使用本地的資源進行頁面渲染。
iOS和Andorid對於攔截Webview中靜態資源請求的方式不太同樣,因此在預加載HTML模板中,須要對iOS和Android分別作邏輯。我是藉助 webpack plugin 和後臺的golang模板引擎來實現的。大體代碼以下:
<!DOCTYPE html> <html> <head> ... <script> var __articleContent__ = JSON.stringify({{.articleContent}}); </script> {{if eq .ostype "ios"}} <link rel="stylesheet" type="text/css" href="./**CSSURL**/"/> {{else}} <link rel="stylesheet" type="text/css" href="/**CSSURL**/"/> {{end}} </head> <body> ... <main></main> {{if eq .ostype "ios"}} <script src="./**JSURL**/"></script> {{else}} <script src="/**JSURL**/"></script> {{end}} ... </body> </html>
客戶端從預加載接口獲取了靜態資源後,會進行版本校驗以及資源完整性校驗,纔會決定是否使用該預加載資源。若是HTML請求的資源與預加載的資源沒法匹配,會去網絡獲取資源。當預加載出錯時,客戶端會走老的那一套邏輯,即:訪問H5文章底層頁的連接。
本文總結了特定場景下,App內的H5頁面首屏性能優化方案。最終上線後的詳細數據就再也不給出了,只能說:肉眼可見的快。整個方案是由前端發起的,在方案實施的過程當中,我也學到了挺多的東西,不單單是技術上的。符合預期。