传统流程
通常将html、js、css等静态资源放入cdn上,然后页面加载后,再通过CGI去拉取最新的 数据,进行拼接展示。 这样可以利用CDN的多低部署和就近接入等优势,同时提高了服务器的并发能力
CGI是啥:不是一种语言,也不是一种技术,而是一种模式,Common Gateway Interface,简称CGI。在物理上是一段程序,运行在服务器上,提供同客户端 HTML页面的接口,“通用网关接口”,这就是CGI的中文意思。
换句话,只要是提供HTML的服务器端程序都可以叫CGI,APS、PHP、JSP这些都是,你用C语言写一个可以提供HTML的服务器端EXE文件,也叫CGI。
- 用户点击后,经过终端一系列初始化流程 ,比如进程启动、Runtime初始化、创建webview等等;
- 完成webview初始化后,开始去CDN上请求html加载页面;
- 页面发起CGI请求对应的数据或者通过localStorage获取数据,数据回来后再对dom进行操作更新。
概括:
初始化 webview -> 请求页面 -> 下载数据 -> 解析HTML -> 请求 js/css 资源 -> dom 渲染 -> 解析 JS 执行 -> JS 请求数据 -> 解析渲染 -> 下载渲染图片
可以看出上述流程存在着几个问题:
微信图片_20170910170542.jpg- 从外网统计数据来看,用户的终端耗时在1s以上,这意味着在这1s多的时间内,网络是完全空闲等待的,非常浪费;
- 页面的资源和数据完全依赖于网络,特别是用户在弱网络场景下,页面会出现很长时间的白屏,体验非常差;
- 因为页面的数据依赖于动态拉取,加载完页面后,往往看到的是一些模块先转菊花,再展示,体验也是非常不好的。同时这里涉及到较多数据更新,经常要更新DOM ,性能上也有不少开销。
优化方案
终端优化
针对终端耗时1s以上的情况,做以下优化
- webview 池:可以用两个或多个 webview 重复使用,而不是每次打开 H5 都新建 webview。不过这种方式要解决页面跳转时清空上一个页面,另外若一个 H5 页面上 JS 出现内存泄漏,就影响到其他页面,在 APP 运行期间都无法释放了
- 预加载:在一个进程内首次初始化 webview 与第二次初始化不同,首次会比第二次慢很多。原因预计是 webview 首次初始化后,即使 webview 已经释放,但一些多 webview 共用的全局服务或资源对象仍没有释放,第二次初始化时不需要再生成这些对象从而变快。我们可以在 APP 启动时预先初始化一个 webview 然后释放,这样等用户真正走到 H5 模块去加载 webview时就变快了。
服务端渲染-静态直出
服务器端拉取首屏数据通过Nodejs进行渲染。然后生成一个包含了首屏数据的html文件,这样展示首屏的时候,就可以解决内容转菊花的问题了。
缺点是:服务器端处理耗时增加。不过现在html都会发布到cdn上,webview直接从cdn上面获取,这块耗时对用户没有造成影响。
客户端优化
- 降低请求量: 合并资源、减少HTTP请求。minify/gzip压缩、webp、lazyload。
- 加快请求速度: 预解析dns,减少域名数、并行加载、cdn分发
- 缓存: http协议缓存请求、离线缓存mainfest、离线数据缓存localStorage
- 渲染: js/css优化,加载顺序
离线预推
微信图片_20170910171745.jpg页面发布到cdn上后,webview需要发起网络请求去拉取,当用户在弱网情况下,这个加载时间就很长。于是我们通过离线预推的方式,把页面的资源提前拉取到本地。当用户加载资源的时候,相当于从本地加载,即使没有网络,也能展示首屏页面,这个也就是大家熟悉的离线包。
微信图片_20170910172013.jpg预加载
用户收到push的时候,可以利用后台来提前获取数据
总结优化思路:
从终端优化、客户端优化、服务端渲染、离线预推、预加载等方面优化,思路从
缓存、预加载、并行方面出发考虑。缓存一切网络请求、尽量在用户打开之前就加载好所有内容,能并行做的事情不串行做。
网友评论