Applets use two threads

In this architecture, the view layer uses WebView as the rendering vector, while the logic layer uses a separate 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 startup process of a small program

  • 1. Small program initialization: wechat initialization of the small program environment: includingJs engineandWebView Class, and inject the common base. 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.
  • 2, download the small program code package to download the small program business code package: download is not the source code of the small program, but compiled, compressed, packaged after the code.
  • 3, load the small program code package to download the completion of the code package injection execution. At this point,app.js, where the page residesJs fileAnd all the others wereJs file for requireIs automatically executed once, and the applet base library completes the registration of all pages.
  • 4. Initialize the home page of the small program to pull data and transfer it from the logical layer to the view layer for rendering

How setData works

  • 1, callsetDataMethods;
  • 2. The logical layer executes onceJSON.stringifyTo get rid ofsetData In the dataDo not transferTo convert the data to be transferred to a string and concatenate it to a specificJS script, and through theevaluateJavascriptExecute the script to transfer the data to the rendering layer.
  • 3. After the rendering layer receives it,The WebView JS threadThe script is compiled and the data to be updated is put into the render queueThe WebView threadRender pages at leisure.
  • 4,The WebView threadTo begin rendering, willdata andsetDataData is applied inWXMLOn the fragment, you get a new node tree. Through the new virtual node tree and the current node treediffCompare, and update the difference section toUIThe view. Finally, thesetData Data merge intodata, and replace the old node tree with a new one for the next re-rendering

Applets official performance metrics

  • 1. The first screen time shall not exceed5 seconds;
  • 2. The rendering time shall not exceed500ms;
  • 3. Call every secondsetDataThe number of times does not exceed20 times;
  • 4,setDataThe data inJSON.stringifyAfter no more than256kb;
  • 5, pageWXMLThe node is less than1000The node treeLess than 30 layers deep.Number of child nodesNo greater than60;
  • 6. All network requests return results within 1 second;

Small program optimization

1. Subcontract and use

Subcontract preloading (by configuring preloadRule) puts low-hit pages into subpackages and loads them on demand; The pages you need to access at startup and their dependent resource files should be placed in the main package. There is no need to wait until the user clicks on the sub-package page to download the sub-package. Instead, according to the later data, the sub-package can be preloaded to load the sub-package page that the user may click on the current page. When the user clicks, the sub-package page can be directly jumped. It can be determined by the user’s network type. Preloading is performed only when the user is in good network conditions.

2, the use of independent subcontracting technology (feel Kepler gold process source can be independent subcontracting)

If you want to jump into a subpackage, you still load the main package and then load the subpackage; The independent subcontracting technology is adopted, which is different from the subpackage and unrelated to the main package. In the independent subpackage, users only need to download subcontracting resources.

3. Asynchronous requests can be made on the pageonLoadIs loaded

4. Take advantage of caching

Storage API is used to cache asynchronous data with low change frequency. During the second startup, the cached data is first used for initial rendering, and then the asynchronous data is updated in the background

5. Give feedback

Timely feedback to the interactive operations that users need to wait for, to avoid users thinking that the small program is stuck first feedback, and then request. For example, a “like” button can change its style before making an asynchronous request.

6. Use custom components as much as possible for detachable parts

Updates to custom components do not affect updates to other elements on the page, and each component has its own logical space, data, style environment, and setData calls

7, avoid improper use of onPageScroll

Avoid complex logic in onPageScroll, avoid frequent use of setData in onPageScroll, avoid frequent query of several points of information in onPageScroll (selectQuery)

8. Reduce resource files directly embedded in code packages; Images are placed in the CDN, using the appropriate image format

9. SetData optimization

(1) It is better not to set the data irrelevant to the interface rendering in data, you can consider setting it 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

(2) Do not call setData too frequently, and merge multiple setData calls into one setData call

(3) The performance of data communication is positively correlated with the amount of data. Therefore, if some data fields are not displayed in the interface and the data structure is complex or contains long strings, setData should not be used to set these data

(4) List partial update when updating a certain data of the list. 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

(5) do not setData in the background page (that is, do not use setData after page jump) page jump, code logic is still in execution, at this time multiple WebViews are sharing a JS process; Background setData operations will seize the foreground page rendering resources;

10. Avoid too many page nodes

During the initial rendering of a page, the construction of a rendering tree, the calculation of node geometry and the time cost of drawing nodes to the screen are all positively correlated with the number of page nodes. The more page nodes there are, the longer the rendering time is.

Each time setData is executed to update the view, the WebView JS thread traverses the node tree to calculate the difference between the old and new nodes. When the number of page nodes is larger, the time cost of calculation is larger. Reducing the number of nodes in the node tree can effectively reduce the time cost of re-rendering.

11. Improper use of events

(1) Remove unnecessary event binding (bind and catch in WXML), thus reducing the amount of data and times of communication; (2) The dataset of target and currentTarget needs to be transmitted during event binding, so do not place too large data in the data prefix attribute of the node

12. Move logic backward and streamline business logic

For example, when we generate shared pictures, for example, when we receive new vouchers, whether the new person meets the risk control conditions and the final receipt of vouchers will be encapsulated as an interface

13. Data prepull (important)

Small program official provides developers with a small program in cold start when the ability to pull ahead of the third party interface developers.weixin.qq.com/miniprogram… Pre-pull can pull the business data from the third-party server in advance through the wechat background when the small program is cold started. When the code package is loaded, the page can be rendered more quickly, reducing the user waiting time, and thus improving the opening speed of the small program

14. Prepull when jumping

NavigateTo (wx. NavigateTo, for example) can request the main interface of the next page in advance and store it in the global Promise object. After the next page loads, the data can be read from the Promise object

15. Delay requests for non-critical render data

The small program will initiate a aggregation interface request to obtain the data of the main module, while the data of the non-main module will be obtained from another interface. By means of splitting, the call delay of the main interface is reduced, and the data volume of the response body is reduced, and the network transmission time is reduced.

16. Split rendering

On the basis of the main module, the first screen module and non-first screen module are divided again (such as Beijing choose good goods guess you like the module). The non-first screen module and non-main screen module will be rendered only after all the first screen modules are rendered, so as to ensure that the first screen content is presented at the fastest speed

17, interface aggregation, request merge (mainly to solve the limitation of API call times in the small program)

Limit on the number of API calls in applets: the maximum concurrency limit for Wx. request (HTTP connection) is 10; The maximum concurrency limit for wx.connectSocket (WebSocket connection) is 5;

Event bus, which replaces the communication mode of data binding between components

Data transfer from parent to child is accomplished through EventBus, which is a publish/subscribe model

The big picture is cropped for multiple blocks

Long list optimization

(1) Do not use concat every time when loading more and more data, concat every new page of data into the list, so that the list will become longer and longer each time setData, rendering speed will be slower and slower. (2) Batch setData, Reduce the number of setData ata time. Don’t set the Data list at once. Instead, setData to the list in batches for each page

this.setData({ 
    ['feedList[' + (page - 1) + '] ']: newVal, 
}) 
Copy the code

. (3) using the official IntersectionObserver relativeToViewport parts beyond the visual area or uninstall (applicable to a loading list data of many beyond the two shown on the screen height of content)

this.extData.listItemContainer.relativeToViewport({ top: showNum * windowHeight, bottom: showNum * windowHeight }) 
    .observe(`#list-item-The ${this.data.skeletonId}`.(res) = > { 
        let { intersectionRatio } = res 
        if (intersectionRatio === 0) { 
            console.log('[unload]'.this.data.skeletonId, 'Out of range, unload from page') 
            this.setData({ 
                showSlot: false})}else { 
            console.log('[enter]'.this.data.skeletonId, 'Reach the desired range, render into the page')
            this.setData({ 
                showSlot: true.height: res.boundingClientRect.height 
            }) 
        }
    }) 
Copy the code

21, reasonable use of function shake and throttling, to prevent the occurrence of repeated click and repeated requests to avoid frequentsetDataAnd render, do the anti-shake function, the time is600ms