Web page performance optimization is a cliche topic, but wechat small program because of the dual-thread architecture design, with the traditional Web page is not the same. Therefore, today to explore the micro channel small program performance optimization problem.
First of all, we need to ask a question: from opening wechat small program to home page display in front of you, what process to go through? (This can be compared to another common front-end problem: how a Web page goes from entering a URL to presenting a page.)
1. Start the process
I’m sure you’re familiar with how Web pages are rendered. What about small programs? Briefly, small programs go through the following startup process:
-
Small program initialization: wechat initialization of small program environment: including Js engine and WebView initialization, and injection into the common base library. This step is done by wechat, which is ready before the user opens the small program. The running environment of the small program is preloaded.
-
Download small program code package Download small program service code package: Download the compiled, compressed, and packaged code instead of the source code of the small program.
-
Load the applets code package to perform injection execution of the code package upon completion of the download. At this point, app.js, the js file in which the page is located, and any other JS files required are automatically executed once, and the applet base library completes the registration of all pages.
-
Initialize the applet home page pull data, pass from the logical layer to the view layer, render.
2. Performance optimization
Now that we know the startup process of the small program, we can analyze and optimize the performance of each link.
2.1 Small program initialization
Because this link is implemented by wechat, it is the execution time of the bottom of the small program, so we developers can not control. What is known is that iOS initializes faster than Android.
2.2 Download and loading
Generally speaking: download link is time-consuming link. For code packages less than 1MB, the download time can be controlled within 929ms (iOS) and 1500ms (Android). The key to improving download performance is to control package size.
Common ways to control the size of code packages are as follows:
- Simplify code and remove useless code
- Reduce resource files embedded directly in code packages
- Images are placed in the CDN, using the appropriate image format
If the small program is complex and the total amount of optimized code is still large, subcontracting loading can be adopted to optimize.
It works like this: Normally, the code for the applets will be packaged together and downloaded in one go when the applets start. When subcontracting is used, the code package of the applet can be divided into several: one is the “main package”, which contains the page code and related resources that will be opened immediately when the applet is started; The rest is “subcontracted,” containing the rest of the code and resources. In this way, when the small program starts, only need to download the main package to complete, you can immediately start the small program. This can significantly reduce the download time of applets.
However, another problem appeared at this time. When we visited the subcontracting page, we had to download the subcontracting code before opening the subcontracting page, which made us feel obvious lag and had poor experience.
We can configure preloadRule to preload subpackages: open the home page, load the main package, and silently load other subpackages.
In addition to ordinary subcontracting schemes, small programs also have independent subcontracting schemes. Independent subcontracting is a special type of subcontracting in small programs that can operate independently of the main package and other subcontracting. There is no need to download the main package when entering the applet from the standalone subcontracting page. The main package is downloaded only when the user enters the normal package or main package page. We can use it for separate pages, such as active pages.
2.3 Initializing the Home Page
When it comes to the first screen rendering, there are several optimization suggestions as follows:
-
Request ahead: An asynchronous request can be made during the page onLoad phase without waiting for the page to be ready. It would be better if you could pre-request the core asynchronous request of the current page when the front page is clicked;
-
Make good use of cache: Cache some asynchronous data with low change frequency, which can be directly used when starting up next time;
-
Optimize interaction: During the first screen rendering, use loading effects or display skeleton diagrams to relieve users’ anxiety of waiting.
In fact, the page initialization time is roughly composed of two parts: the initial data communication time and the initial rendering time. Among them, the time index of data communication is the time when the data is organized from the logical layer to the view layer, and the total time can be controlled within 30ms when the amount of data is less than 64KB. The transmission time is generally positively correlated with the amount of data, and the transmission time will increase significantly if the data is too large. Therefore, reducing the amount of data transmission is an effective way to reduce the data transmission time.
After the initial rendering, the view layer can perform an interface update after the developer calls setData.
2.4 setData optimization
2.4.1 Working principle of setData
The biggest difference from traditional browser Web pages is that the applets are based on a two-threaded model: in this architecture, the view layer uses WebView as the rendering carrier, while the logical layer uses independent JavascriptCore as the runtime environment.
Both are independent modules and do not have a direct channel for data sharing. Native JSBrigde is used to transfer data between view layer and logic layer.
The applet updates data to view changes through setData. The complete process is as follows:
- call
setData
Methods; - The logical layer executes once
JSON.stringify
To get rid ofsetData
The non-transferable part of the data, the data to be transferred into a string and concatenated to a specific JS script, and throughevaluateJavascript
Execute the script to transfer the data to the rendering layer. - Once the render layer receives it,
WebView JS
The thread compiles the script, gets the data to update, and waits in the render queueWebView
Render the page when the thread is idle. WebView
When the thread starts rendering, it willdata
和setData
Data is applied inWXML
On the fragment, you get a new node tree. Through the new virtual node tree and the current node treediff
Compare, and update the differences section to the UI view. Finally, thesetData
Data merge intodata
, and replace the old node tree with a new one for the next re-rendering.
2.4.2 setData Precautions
As mentioned above: one setData incurs two costs: the communication cost + the WebView update cost. SetData is one of the most frequently used apis for applets development, and the one most prone to performance issues.
Therefore, the following points should be paid attention to when using:
-
Data that is not related to the interface rendering should not be set in data, but can be set in other fields of the page object.
this.setData({ a: 'Strings related to rendering', b: 'Render independent string'}) // can be optimized to this.setData({a:'Strings related to rendering', }) this.b = 'Render independent string' Copy the code
-
Don’t call setData too often and consider merging multiple setData calls into one setData call;
This.setdata ({a: 1}) this.setData({b: 2}) // Can be optimized to this.setData({a: 1, b: 2}).Copy the code
When you need to call setData on frequently triggered user events (such as PageScroll and Resize events), use debounce and throttle functions properly.
You can also design a DIff algorithm to encapsulate setData again, so that before the setData is executed, the data to be updated is diff compared with the original data, and if the data is the same, the update is skipped. Many applets have similar packages.
-
List partial update When one of the data in a list is updated. Do not use setData to refresh all data. Find the index of the data corresponding to the ID (index is not changed), use setData to perform local refresh.
this.setData({ `list[${index}]` = newList[index] }) Copy the code
-
Use applets properly. Updates to a custom component occur only within the component and do not affect other elements on the page. Because each component has its own logical space, data, style environment, and setData calls. Based on the Shadow DOM model design of custom components, we can encapsulate some function modules (such as countdown, progress bar, etc.) that need to perform setData update frequently in the page into custom components and embed them in the page. When these custom component views need to be updated, the component’s own setData is performed, the comparison of the old and new node trees and the update of the render tree are limited to a limited number of nodes within the component, effectively reducing the rendering time overhead.
Of course, using more custom components is not necessarily better. For every new custom component added to a page, Exparser needs to manage one more component instance and consumes more memory. Therefore, the use of custom components should be reasonable, and the page design should be careful not to abuse tags.
3. Analysis tools
Performance optimization is all about data. However, there is no complete and mature quantitative performance evaluation standard in the small program. At present, the following analysis tools are available for reference:
-
Trace export tool is available from wechat Andoid 6.5.10. Developers can use this feature in the Developer tool Trace Panel. Using the tutorial: developers.weixin.qq.com/miniprogram…
-
Performance panel Starting from wechat 6.5.8, a performance panel is provided to let developers know the performance of small programs. Developers can open the performance panel under the development applets. Open method: Enter the development version of the small program, enter the upper right corner more button, click show performance window
-
Load performance Monitoring In the applet background, we can see load performance monitoring. There are three indicators:
-
Total Startup Time
-
Download time
-
Initial rendering time
Total startup time = Download time + initial rendering time + other time.
After optimization, the data can be compared according to the above tools to judge the optimization effect.
Main Reference Sources:
- Micro channel small program performance optimization scheme
- Micro channel small program rendering performance tuning