The architecture for running Mini Programs is different from the architecture for running traditional HTML5 applications and consists of two parts: WebView and Worker. WebView is responsible for rendering. Worker is responsible for storing data and executing business logic.
How it works
The communication between WebView and Worker is asynchronous. This means that when you call the
setDatamethod, the data is asynchronously transferred from Worker to WebView instead of being immediately rendered.Data needs to be serialized into strings before being transferred by using
evaluateJavascript. The size of data affects the transfer performance.
Optimize the first screen
The definition of the first screen may differ. In this case, the first screen refers to the first page that is meaningfully rendered from the perspective of business logic. For example, for a list page, the first screen refers to the content that is rendered from the list for the first time.
Limit the size of the resource package of a Mini Program
When a user opens a Mini Program, Alipay downloads the resource package of the Mini Program from the relevant content delivery network. The size of the resource package will affect the startup performance of the Mini Program.
Optimization suggestions:
Regularly delete useless image resources. By default, all image resources are included in the resource package.
Limit the sizes of images. We recommend that you do not include large images in the resource package and that you upload large images by using a content delivery network.
Regularly clear useless code.
Use onLoad to request data in advance.
When a Mini Program is running, the lifecycle function
onLoadis triggered on a page. Then, the initial page data is transferred from Worker to WebView for initial rendering.After the initial rendering is complete, a notification is sent from WebView to Worker and the lifecycle function “onReady” is triggered.
For specific Mini Programs, a request for data may be included in the “onReady” function, which slows down the rendering of the first screen.
Optimization suggestion: Use onLoad to request data in advance.
Limit the number of nodes on the first screen that can be rendered at a time
Generally, after a business request receives a response, the setData method triggers to re-render the page. The execution process is described as follows:
Data is transferred from Worker to WebView.
On WebView, a virtual DOM is constructed based on the transferred data, and the virtual DOM is compared against the original DOM from the root node. Then, the rendering starts.
Data needs to be serialized for the communication between Worker and WebView. After the data is transferred to WebView, evaluateJavascript is executed. Therefore, if the volume of data transferred at a time is excessively large, the rendering performance of the first screen is affected.
There may be excessive nodes on WebView or the file structure has excessive directories. For example, the list page of a Mini Program may render more than 100 list items at a time. Each list item contains embedded content. However, only less than 10 list items are displayed on the screen. This causes the comparison to take more time. In addition, due to the fact that this is the rendering of the first screen, a lot of DOMs may be constructed, which will affect the rendering performance of the first screen.
Optimization suggestions:
Limit the volume of data when you call the
setDatamethod. This helps avoid transferring an excessively long list at a time.Do not create excessive nodes for the first screen. The server may request a large volume of data at a time. In this case, do not specify all the data when you call the
setDatamethod. You can specify some of the data and wait a specific period of time, such as 400 ms. The specific period of time varies based on your business. Then, you can call the$spliceDatamethod to transfer the rest of the requested data.
Optimize the logic of the setData method
A change on a page triggers the setData method. Multiple changes on a page may trigger the setData method at the same time to re-render the page. Each of the following interfaces triggers the re-rendering of the WebView of a page:
Page.prototype.setData: triggers the comparison of the whole page.Page.prototype.$spliceData: used for a long list to avoid transferring the whole list and triggering the comparison of the whole page every time.Component.prototype.setData: triggers the comparison from the relevant component node.Component.prototype.$spliceData: used for a long list to avoid transferring the whole list every time and trigger the comparison from the relevant component node.
Optimization suggestions:
Do not frequently trigger the
setDataor$spliceDatamethod on a page or in a component. Some pages may contain countdown logic. However, the countdown logic may have an excessively high frequency that causes millisecond-level triggering.If you need to frequently trigger re-rendering, do not call the
setDataor$spliceDatamethod on the page. Instead, package the relevant resources into a custom component and call thesetDataor$spliceDatamethod in the component for re-rendering.For the rendering of long list data, use
$spliceDatato add data for multiple times. You do not need to transfer the whole list at one time.For a complex page, we recommend that you package the relevant resources into a custom component to avoid calling the
setDatamethod on the page.
Optimization example:
Use the $spliceData method for long lists:
this.$spliceData({ 'a.b': [1, 0, 5, 6] })We recommend that you set data in a specified path, as shown in the following code snippet:
this.setData({
'array[0]': 1,
'obj.x':2,
});Do not use the following code. In the code, this.data is copied, but the attributes are modified.
const array = this.data.array.concat();
array[0] = 1;
const obj={...this.data.obj};
obj.x=2;
this.setData({array,obj});Do not directly modify the data that is obtained by using this. data, as shown in the following code snippet. This breaches the principle of data integrity.
this.data.array[0]=1;
this.data.obj.x=2;
this.setData(this.data)Business logic may be encapsulated into a component. When the user interface of the component needs re-rendering, you only need to call the setData method in the component. However, in some scenarios, the re-rendering of a component is triggered by an event on a page. For example, a page listens to the onPageScroll event. When the event is triggered, the component needs to be notified and start re-rendering. The following code snippets show how to implement this process:
// /pages/index/index.js
Page({
onPageScroll(e) {
if (this.xxcomponent) {
this.xxcomponent.setData({
scrollTop: e.scrollTop
})
}
}
})// /components/index/index.js
Component({
didMount(){
this.$page.xxcomponent = this;
}
})You can bind the component to the page in the didMount method. When you call the component-level setData method from the page, the call only triggers the re-rendering of the component.
Use the key parameter
You can use the key parameter in for to improve performance.
Do not use the key parameter in a block.
Code sample:
<view a:for="{{array}}" key="{{item.id}}"></view>
<block a:for="{{array}}"><view key="{{item.id}}"></view></block>