客戶端內H5頁面的首屏性能優化

寫在前面

本文首發於公衆號:符合預期的CoyPan

性能優化是前端開發中不可避免的一個話題。本文將記錄一次客戶端內H5頁面首屏性能優化的項目。css

背景介紹

信息流App是當下最流行的產品之一,現在日頭條等。我所在的團隊也是在作這樣一款信息流App。App的Feed流是客戶端Native實現的。用戶點擊Feed流中的文章後,會進入到文章底層頁。文章底層頁大部分都是Native實現的,可是有一些文章的數據是非結構化的,Native沒有辦法很好地處理,因此用H5頁面來承接這部分文章。整個業務場景很簡單,用圖表示以下:
圖片描述html

毫無疑問,H5頁面會極大影響App的用戶體驗。所以,H5頁面的首屏性能是十分重要的,要爭取能作到秒開。前端

優化前

優化前,H5底層頁的加載流程以下:webpack

圖片描述

上圖的加載流程是一個很常見的頁面加載流程。在這個流程中,至少包含了四次http請求。每一次http都會拖慢頁面呈現的時間。若是是一個單獨的H5頁面,沒有任何問題,可是這個頁面是在客戶端內,是要爭取作到秒開的。ios

優化方案調研

ssr

服務端渲染。服務端渲染是將數據請求和頁面結構生成放到服務端完成,用戶訪問頁面url時,接口吐出的就是完整的,帶有數據內容的html,首屏速度天然會有提高。可是這裏有幾個問題:golang

一、目前的非結構化文章數據就是一大串HTML字符串,服務端不太好去處理一大串HTML的字符串。web

二、就算實施了ssr,在用戶訪問H5底層頁連接的時候,始終會有一次Http請求,首屏速度依然會收到網絡環境等因素的影響。性能優化

離線包

一個完整的離線包方案,是根據業務模塊配置,把H5頁面和相關資源都打包上傳,而後客戶端在特定的時機對離線包進行預下載,解壓、檢驗等工做,而後在特定的時機使用離線包裏的本地文件等。離線包是一個不錯的解決方案,可是離線包有一個問題:過重了。網絡

輕量級的解決方案

方案概述

權衡了各類因素後,咱們採用了下面的解決方案:性能

圖片描述

  1. 前端在開發上線打包時,產出兩個HTML模板文件,一個用於以前的邏輯,一個用於預加載邏輯。預加載HTML已字符串的形式寫入後臺的配置服務。將產出的js,css文件上傳cdn,而且將cdn地址上傳到後臺保存。
  2. 用戶訪問客戶端時,後臺會經過預加載接口下發預加載數據,客戶端將帶有數據的HTML模板字符串保存在本地,同時下載靜態文件保存。
  3. 用戶訪問H5底層頁時,客戶端直接load本地的HTML模板字符串,同時攔截webview的靜態資源請求,直接使用提早下載好的js,css文件。

總結起來,就是後臺提供預加載接口,準備好H5底層頁須要的Html,文章數據,js,css等,用戶點擊進入到底層頁時,客戶端直接使用本地的資源進行頁面渲染。

方案補充
  • HTML預加載模板相關

    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文章底層頁的連接。

方案總結
  • 直接將數據寫入html,省去了H5頁面請求接口拉取數據的開銷。
  • js,css等靜態資源預加載,須要時直接從本地load,省去了H5頁面經過網絡獲取靜態資源的開銷。
  • 輕量級方案,整個過程可控,H5頁面上線和更新的流程簡單。

寫在後面

本文總結了特定場景下,App內的H5頁面首屏性能優化方案。最終上線後的詳細數據就再也不給出了,只能說:肉眼可見的快。整個方案是由前端發起的,在方案實施的過程當中,我也學到了挺多的東西,不單單是技術上的。符合預期。

相關文章
相關標籤/搜索