在开发小程序应用中,QA发现过几回页面白屏的状况,苦于难易复现和调试,故想对小程序白屏问题进行一番探究。javascript
从小程序官方开发者文档得知,微信小程序运行在三端:iOS(iPhone/iPad)、Android和用于调试的开发者工具。三端的脚本执行环境以及用于渲染非原生组件的环境是各不相同的[1]:html
下面说说WKWebView、Mobile Chrome 53/5七、Mobile Chrome 53是什么。前端
在Apple公司的开发者文档网站上,有对WKWebView进行介绍,简单来讲,WKWebView是一个为app内置浏览器渲染交互式网页内容的组件,用于替换老版本的UIWebView组件[2]。不论是UIWebView,仍是WKWebView,它们都属于IOS WebView。咱们能够把WebView理解为手机操做系统的一个系统级的组件。不论是手机内置的浏览器,仍是其余app,好比微信等,只要你想呈现交互式的网页内容,均可以调用WebView去完成这件事情。Android WebView亦是如此[3]。java
如今咱们能够把WKWebView称为IOS端的WebView,那么Android端的Mobile Chrome 53/57,或者Mobile Chrome 53又是什么,这两个跟WebView又是什么关系呢? 咱们能够把Mobile Chrome 53/57理解为Chrome for Android 537版本,这里的537是指Chrome的排版引擎(layout engine)采用的WebKit内核版本,具体参考Google Chrome version history[4]。须要指出的是,53/57是否是就是537,这里存疑,没有查到有效的参考资料,可是这个对咱们的研究应该没有什么影响,能够不予考虑。到这里,又引入了两个概念:layout engine、WebKit内核。接下来简单介绍一下layout engine和WebKit内核。android
咱们都知道浏览器有两个重要的引擎:渲染引擎(rendering engine,也称layout engine,即上面提到的排版引擎,后续为了方便,统一描述为渲染引擎)和JS引擎。其中渲染引擎负责解析网页内容,计算显示方式,输出至显示设备。JS引擎则负责解析JavaScript语言,实现网页的动态交互效果。最开始时渲染引擎和JS引擎并无区分的很明确,后来JS引擎愈来愈独立,内核就倾向于只指渲染引擎,即浏览器内核就是该浏览器采用的渲染引擎,主要参考X5内核调研报告[5]。在后续的讨论中,浏览器内核就单指渲染引擎。web
那WebKit内核又是什么?这个不得不追溯WebKit的历史了。1998,自由软件社区KDE开发了HTML排版引擎KHTML和JavaScript解析引擎KJS,也就是现代浏览器两个重要的引擎。Apple公司的开发者Don Melton于2001年在KDE的基础之上开始了WebKit项目。刚开始时,WebKit仅为KDE的复刻,咱们能够理解为WebKit是KDE基础上fork出来的分支。后来,在WebKit项目中,KHTML被命名为WebCore,KJS被命名为JavaScriptCore,主要参考维基百科[6]。至此,咱们能够回答,至少针对Apple的产品来讲,浏览器内核就是WebKit,即渲染引擎采用的是WebKit内核。小程序
webkit项目是Apple公司发展自家浏览器启动的项目。Google公司在发展Chrome浏览器也成立了Chromium项目。在Chromium项目中,JavaScript解析引擎采用Google本身开发的大名鼎鼎的V8引擎,渲染引擎采用的是WebKit内核。到2013年7月份,Chromium项目将渲染引擎替换为Blink引擎,并在Chrome28及后续的版本上采用[4][7]。Blink引擎是Google在WebKit项目中的WebCore基础上fork出来的一个分支[8][9]。咱们能够用一幅图把KDE、WebKit和Chromium串联起来:微信小程序
如今,咱们再回过头来看一下Mobile Chrome 53/57,或者Mobile Chrome 53,其实它的内核仍是从WebKit上演化而来。绕了这么远,只为一句话:小程序就是运行在WebView之上。那么咱们的初衷,研究小程序白屏问题,其实就是在探究WebView白屏问题。若是要更详细一点,那就是WKWebview、Android WebView白屏的缘由。浏览器
关于WKWebview白屏,网上罗列的常见缘由大体有如下几种:微信
针对缘由3,解决的方案是判断IOS系统版本,小于8.2的使用UIWebView。若是站在小程序开发者的角度,这个跟咱们好像没有关系。小程序是个平台,咱们在这个平台上开发咱们的小程序应用,若是小程序也有这个问题,那只能由小程序团队去解决这件事情。还有,好比缘由4,咱们该嵌套仍是得嵌套,有问题也是小程序团队去解决。至于缘由2,若是是小程序原生开发的话,页面间的跳转URL包含中文也是能正常跳转的,这个应该是小程序内部兼容了。可是缘由1,这个跟咱们就有很大的关系了,好比咱们定义了大量的变量,使用完了却没有释放,那么这部份内存在小程序销毁以前会被一直占用。再好比咱们在某一刻操做了某个比较大的变量,可能在短期内,内存使用量也会飙升。一样的,对于致使Android WebView白屏的问题,绝大部分也只能由小程序团队去解决。
这样一来,从开发小程序应用的前端角度来讲,咱们可以把握的是尽可能避免因为内存使用紧张致使的部分WebView被回收而出现的白屏问题。至此,咱们研究的小程序白屏问题,能够转向对小程序内存优化的研究。
下面总结一下平时开发过程当中可能会致使内存警告的操做:
使用大图片和长列表图片。根据小程序团队分析过的大部分案例,大图片和长列表图片的使用,都会引发WKWebview被回收[10]。其中长列表页图片是指页面包含数目较大的列表,每一个列表里面又引用了图片。
随意定义变量,因为小程序的机制而又没有获得释放。如下四种场景下定义的变量,即便离开当前页面,变量也不会被回收:
定义在Page构造器外层的全局变量。
定义在data内部的数据。
定义在Page内部,类data数据。
挂载到getApp().globalData上的数据。
假如咱们在testvar页面定义了上述变量,由testvar经过navigateTo跳转到下一个页面otherpage,在页面otherpage里面咱们能够经过getCurrentPages()获取页面testvar的引用,进而获取里面的变量。经过navigateTo打开新页面,上一个页面进入页面栈,而且该页面只是hide,并非unload[11]。小程序框架的页面栈最多可支持10层页面。设想一下,那些具备复杂交互的页面,每层页面都附带了众多的数据,甚至包含不少图片,再考虑多层页面并存的问题,那内存使用量将是很可观的。在页面栈里面的页面unload以前,都会形成持续的内存占用。
短期内大数据操做。假设在某个时间点,咱们须要对接口返回的大量数据进行操做,可能会形成瞬时的内存占用。
列表数据的持续累加,致使某个数据异常大。设想一下,假如咱们的列表页有不少条数据,每通过一次分页请求,咱们就把新的数据concat到已有的数据之上,长此以往,这条数据可能会变成巨无霸,逐渐侵蚀咱们的内存。
所幸的是,上述这些可能形成内存大量占用的操做,咱们是能够避免或者优化的。
但愿你们进行批评和指正!
参考文献: [1]: developers.weixin.qq.com/miniprogram… [2]: developer.apple.com/documentati… [3]: developer.android.com/reference/a… [4]: en.wikipedia.org/wiki/Google… [5]: juejin.im/post/5a3522… [6]: zh.wikipedia.org/wiki/WebKit [7]: zh.wikipedia.org/wiki/Google… [8]: zh.wikipedia.org/wiki/Chromi… [9]: zh.wikipedia.org/wiki/Blink [10]:developers.weixin.qq.com/miniprogram… [11]: developers.weixin.qq.com/miniprogram…