In the development of small program application, QA has found several cases of page blank screen, which is difficult to reproduce and debug, so I want to explore the problem of small program blank screen.
According to the official developer documentation of the mini program, wechat mini program runs on three ends: iOS (iPhone/iPad), Android and developer tools for debugging. The three-end script execution environment and the environment used to render non-native components are different [1] :
- On iOS, the javascript code of the logic layer of small program runs in JavaScriptCore, and the view layer is rendered by WKWebView. The environment is iOS8, iOS9, iOS10.
- On Android, older versions of the small program logic layer of javascript code run in X5 JSCore, the view layer is rendered by X5 based on Mobile Chrome 53/57 kernel;
- In the new version, the javascript code for the applet logic layer runs in V8, and the view layer is rendered by our own XWeb engine based on the Mobile Chrome 53 kernel.
- On the development tools, the javascript code for the applet logic layer runs in nw.js and the view layer is rendered by Chromium 60 Webview.
What is WKWebView, Mobile Chrome 53/57, Mobile Chrome 53?
In the developer documentation website of Apple, WKWebView is introduced. To put it simply, WKWebView is a component that renders interactive web content for the app built-in browser, which is used to replace the old VERSION of UIWebView component [2]. UIWebView, WKWebView, they’re all IOS WebViews. We can think of WebView as a system-level component of a mobile operating system. Whether it is the built-in browser of mobile phone, or other apps, such as wechat, as long as you want to present interactive web content, you can call WebView to complete this matter. The same is true for Android WebView [3].
Now we can call WKWebView a WebView on IOS, so what is Mobile Chrome 53/57 or Mobile Chrome 53 on Android, and what is the relationship between these two and WebView? Mobile Chrome 53/57 is Chrome for Android 537, which is the WebKit version of Chrome’s layout engine. For details, see Google Chrome Version History [4]. It should be pointed out that whether 53/57 is 537 is questionable here, and no effective reference materials have been found, but this should have no impact on our research and can be ignored. Two concepts were introduced: Layout Engine and WebKit kernel. Let’s take a quick look at layout Engine and the WebKit kernel.
We all know that there are two important engines in browsers: rendering engine and JS engine. We’ll focus on rendering engine and layout engine. Rendering engine is responsible for parsing web page content, calculating the display mode, output to the display device. JS engine is responsible for parsing JavaScript language to achieve dynamic interaction effect of web pages. At the beginning, there was no clear distinction between rendering engine and JS engine. Later, JS engine became more and more independent, and kernel tended to refer only to rendering engine, that is, browser kernel is the rendering engine adopted by the browser, mainly referring to X5 kernel research report [5]. In subsequent discussions, the browser kernel refers solely to the rendering engine.
What is the WebKit kernel? This has to go back to the history of WebKit. In 1998, the free software community KDE developed the HTML typesetting engine KHTML and the JavaScript parsing engine KJS, which are two important engines in modern browsers. Apple developer Don Melton started the WebKit project in 2001 based on KDE. At the beginning, WebKit was just a copy of KDE. We can understand that WebKit is a fork based on KDE. Later, in the WebKit project, KHTML was named WebCore and KJS was named JavaScriptCore, mainly referring to Wikipedia [6]. At this point, we can answer that, at least for Apple products, the browser kernel is WebKit, that is, the rendering engine uses the WebKit kernel.
The WebKit project was started by Apple to develop its own browser. Google is developing its Chrome browser and has a Chromium project. In the Chromium project, the JavaScript parsing engine uses Google’s own famous V8 engine and the rendering engine uses the WebKit kernel. By July 2013, the Chromium project replaced the rendering engine with Blink engine and adopted it on Chrome28 and subsequent versions [4][7]. Blink Engine is a branch fork of Google based on WebCore in the WebKit project [8][9]. We can concatenate KDE, WebKit and Chromium with a graph:
Now, let’s go back to Mobile Chrome 53/57, or Mobile Chrome 53, which actually evolved from WebKit. All this detour, just one sentence: the applet is running on top of the WebView. So our original intention, study small program white screen problem, in fact, is to explore the WebView white screen problem. If you want to be more detailed, that is why WKWebview, Android WebView blank screen.
About WKWebview white screen, the common reasons listed online are roughly the following:
- When the memory usage is large, the WebContent Process crashes, resulting in a blank screen.
- The URL is invalid or contains Chinese characters.
- When WKWebview was first launched, it occasionally had a white screen in IOS8.0 to 8.2
- Due to the nested structure of scroll components, no refresh issues.
For reason 3, the solution is to determine the IOS version and use UIWebView if it is smaller than 8.2. If standing in the small program developer’s point of view, this seems to have nothing to do with us. The applets are the platform on which we develop our applets. If the applets have this problem, it’s up to the applets team to solve it. Also, for reason 4, should we nest or should we nest? If there is a problem, it is the applets team that solves it. As for reason 2, if it is the small program native development, the jump URL between pages including Chinese can also jump normally, this should be the small program internal compatibility. But reason 1, this is very relevant to us, for example, we defined a large number of variables, use the end but do not release, then this part of the small program will be used until the destruction. For example, if we operate on a large variable at a certain moment, the memory usage may soar in a short period of time. Similarly, most of the problems that cause Android WebView to go blank can only be solved by the applets team.
In this way, from the development of small application front-end point of view, we can grasp is as far as possible to avoid memory use constraints caused by part of the WebView is recycled and the white screen problem. At this point, we study the small program blank screen problem, can turn to the small program memory optimization research.
Here’s a summary of the actions that might cause a memory warning during normal development:
-
Use large images and long list images. According to most cases analyzed by the small program team, the use of large images and long list images will cause WKWebview to be recycled [10]. The long list page picture refers to the page contains a large number of lists, and each list is referenced in the picture.
-
Arbitrarily defined variables are not released due to the mechanism of applets. Variables defined in the following four scenarios will not be reclaimed even if they leave the current page:
-
Global variables defined outside the Page constructor.
-
Data defined within data.
-
Class data defined inside the Page.
-
Data mounted to getApp().globalData.
NavigateTo = otherPage; getCurrentPages() = testVar (); And get the variables inside. NavigateTo opens a new page, the previous page goes to the page stack, and this page is just hide, not unload[11]. The page stack of the applets framework can support up to 10 pages. If you think about pages with complex interactions, each layer of pages has a lot of data, and even a lot of images, then the memory usage can be significant if you consider multiple layers of pages. There is a continuous memory footprint until pages unload in the page stack.
-
-
Big data operation in a short time. Suppose that at some point in time we need to operate on a large amount of data returned by the interface, which may cause an instantaneous memory footprint.
-
Continuous accumulation of list data, resulting in an abnormally large data. Imagine if we had a list page with a lot of data, and every time we made a paging request, we concatenated new data onto the existing data. Over time, this data could grow into a giant and eat into our memory.
Fortunately, these potentially memory intensive operations can be avoided or optimized.
- For large images in Reason 1, we can compress them appropriately. What if you can’t press any more, or if the image has to be this big, or if a single image is not big, but there are too many lists that result in too many references? Ok, this can be put aside for now, and the corresponding solution will be put forward in the subsequent discussion.
- For reason 2, we need to combine the actual business scenarios, for those variables that can be discarded after use and do not need to exist with the whole life cycle of the page, do not use those four ways to define data.
- For reason 3, we can try to negotiate with the interface developer to avoid the interface returning a large amount of data at once through paging or other methods.
- For reason 4, the nature of the reason is that continuous paging requests cause new data to be continuously added to the existing data, so in this scenario, we need to discard some of the existing data. There is a principle for discarding existing data. Imagine a scenario where we go to the list page list, and we define listData to hold the data that comes in for each page request. The first page of data comes in, and listData only contains the first page of data. The second page of data comes in, and we concat the new data onto the first page. At this point, listData contains the data from the first and second pages. The data for the third page comes in, and listData contains the data for the first three pages. Now let’s stop and think, we are presenting the user with page 3 of data, the first page of data is not visible, since it is not visible, why not throw it away? If the user swipes up and needs to display the first page of data, we can request the first page of data again. ListData discards part of the data, which will be timely feedback to the View layer, and some nodes of the View layer will also be destroyed, so that part of the memory occupied by the App Service layer and the View layer will be released. Of course, the solution we propose is to solve the problem of continuous paging requests causing new data to be continuously added to the existing data. As for whether to adopt, under what scenarios to discard the existing data, and which data to discard, all these need to be evaluated and weighed based on the actual business.
Hope everybody carries on the criticism and corrects!
Reference: [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. Cn/post / 684490… [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…