客户端内H5页面的首屏性能优化

写在前面

本文首发于微信公众号:符合预期的CoyPanjavascript

性能优化是前端开发中不可避免的一个话题。本文将记录一次客户端内H5页面首屏性能优化的项目。css

背景介绍

信息流App是当下最流行的产品之一,现在日头条等。我所在的团队也是在作这样一款信息流App。App的Feed流是客户端Native实现的。用户点击Feed流中的文章后,会进入到文章底层页。文章底层页大部分都是Native实现的,可是有一些文章的数据是非结构化的,Native没有办法很好地处理,因此用H5页面来承接这部分文章。整个业务场景很简单,用图表示以下:html

毫无疑问,H5页面会极大影响App的用户体验。所以,H5页面的首屏性能是十分重要的,要争取能作到秒开。前端

优化前

优化前,H5底层页的加载流程以下:java

上图的加载流程是一个很常见的页面加载流程。在这个流程中,至少包含了四次http请求。每一次http都会拖慢页面呈现的时间。若是是一个单独的H5页面,没有任何问题,可是这个页面是在客户端内,是要争取作到秒开的。webpack

优化方案调研

ssr

服务端渲染。服务端渲染是将数据请求和页面结构生成放到服务端完成,用户访问页面url时,接口吐出的就是完整的,带有数据内容的html,首屏速度天然会有提高。可是这里有几个问题:ios

一、目前的非结构化文章数据就是一大串HTML字符串,服务端不太好去处理一大串HTML的字符串。golang

二、就算实施了ssr,在用户访问H5底层页连接的时候,始终会有一次Http请求,首屏速度依然会收到网络环境等因素的影响。web

离线包

一个完整的离线包方案,是根据业务模块配置,把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页面首屏性能优化方案。最终上线后的详细数据就再也不给出了,只能说:肉眼可见的快。整个方案是由前端发起的,在方案实施的过程当中,我也学到了挺多的东西,不单单是技术上的。符合预期。

相关文章
相关标签/搜索