If you want to optimize the performance of wechat applets, there are two key points:

  • Improve loading performance
  • Improve rendering performance

Next, introduce them respectively:

Improve loading performance

First, ask the question, what happens when the user clicks on the applet?

The three states in the figure above, which we often encounter, correspond to the following three states of the applet:

  • White screen with three dots (left) : download code package stage
  • No three-point white screen (middle) : business code injection and rendering phases
  • Loading (right) : Asynchronously requesting data in business code

In general, the applets presented to the user actually go through the following two stages:

  • Load the runtime environment
  • Download the code package

The two phases are described below:

The running environment is preloaded

This step is done by wechat. Wechat will have prepared the environment before users open the mini program. After users click the entrance of the mini program, they can directly download the code package of the mini program.

Download the code package to start the applet

Small program code package inside the code, not small program source code, but compiled, compressed, packaged after the code package.

In the figure below, the “preloading” on the left corresponds to the preloading of the running environment, and the “applet start” on the right corresponds to the downloading of the code package to start the applet.

The running environment provided by applets is divided into the logic layer (AppService) and the view layer (webView). The logic layer is where javascript is executed, and the view layer is where the page is rendered. When the code package of the applet is downloaded, the business code is injected into the logic layer and the rendering layer respectively.

The most important thing to improve loading performance is to control the size of the package, which is also the official statement of wechat.

Controls the size of the package

The most direct way to improve the experience is to control the size of the small package, which is basically a 1M code package that takes about a second to download.

Measures to control the size of packets

  • Compress code and clean up useless code

  • Picture on CDN

  • Adopt subcontracting strategy

    • Subcontract preloading
    • Independent subcontracting (version requirements are a little high)

In addition to the control package size described above, optimization for asynchronous requests is also important.

Optimization for asynchronous requests

  • The onLoad phase can initiate the request without waiting for ready
  • The result of the request is cached and used next time
  • The skeleton can be shown on the request first
  • Give feedback before you ask. For example, a “like” button can change its style before making an asynchronous request.

Improved rendering performance

SetData stem what

Every call of setData is a communication from the logic layer to the rendering layer. This communication is not directly transmitted to the webView, but through the Native layer, so the communication cost is very high.

The rendering layer also needs to re-render after receiving the communication, so, emMM, one setData incurs two costs: the communication cost + the webView update cost.

At data transfer time, the logical layer performs a json.stringify to remove any untransportable parts of the setData data, and then sends the data to the view layer. At the same time, the logical layer will also merge the data field set by setData with data, so that developers can use this.data to read the changed data.

Reduce the amount of setData

If the data does not affect the rendering layer, do not put it in setData

Merge setData requests to reduce the number of communications

That makes sense

Partial update of the list

In a list, there are n data, using the way of pull-up loading more, if this time want to like a certain data operation, but also timely see the effect of the like

At this point, you can use setData global refresh, after the completion of the like, re-obtain data, global re-rendering again, the advantage of doing so is: convenient, fast! Disadvantages: the user experience is extremely bad, when the user brushes more than 100 data, there will be a large amount of blank period for re-rendering (no rendering over).

If you do a layout refresh, you pass in the id that you liked, and you know what data you clicked on.

Retrieve the data again, find the subscript of the data corresponding to the ID (index is not changed), use setData for local refresh

this.setData({
    list[index] = newList[index]
})
Copy the code

Be careful with the js of the background page

The applet may have n pages, all of which, while having their own WebView (rendering layer), share the same JS runtime environment. That is, when you jump to another page (let’s say PAGE B), the timer and other JS operations on this page (let’s say page A) are still going on, and will not be destroyed, and will preempt resources on page B.

In the H5 environment, when we jump to another page, the js environment of the old page will be automatically destroyed, and the timer will destroy everything, so we don’t need to care about what js code in the old page might still be executed. But in applets, we have to manually “clean up” such code.

Be careful onPageScroll

The pageScroll event, which is also a communication, is a communication from the WebView layer to the JS logic layer. This communication is also expensive, considering that the event is frequently called, the callback function with complex setData, EMMMMM, performance will be poor.

Get node positions carefully

In the h5 environment, in order to achieve lazy loading and pull-down loading, we have to get the location of the node.

We could have easily implemented it with a new API — intersectionObject (mainstream browsers such as Google already support it), but wechat’s built-in X5 browser unfortunately does not support it.

However, in the mini-program environment, wechat has found its conscience and supports intersectionObject API, so it is best to use this API to obtain node information.

Use applets whenever possible

The update of a custom component is done only within the component and is not affected by other non-separable contents of the page. For example, the timing module of some operation activities can be isolated and made into a timing component. The update of the timing component will not affect the update of other elements on the page. Each component will also have its own separate logical space. Each component has its own separate data, setData calls

Optimization result

Compared to the above optimization strategy, the most important thing is to find performance bottlenecks in applets. In my own optimization practice, I encountered the following problems:

Pull down to load more, special special cards, and use the list local update technique to find little improvement in performance. Later, it was found that the home page needed to listen for scroll events, resulting in frequent triggering of scroll events. There were time-consuming operations in the callback function, resulting in the blocking of onreachBottom events. In other words, it took about 1~2 seconds to initiate the request for the next page. Cancel the monitoring of scroll event, and the loading time of scroll event >4s should be controlled within 1s.

Reprinted fromwww.jianshu.com/p/d4fb22509…