Why this article

Want to see dry goods can directly jump to the body……

Small program centerBaidu APP small program traffic distribution entrance, from the Baidu people can enter the center.

The small program center is big or small, and belongs to the kind of sparrow is small and has all the five organs. From 18 years to now, it has experienced two years of iteration, handled more than 20 development, about 1000 commit times, and developed into a relatively mature product. Product development to a certain stage, began to show some technical bottlenecks, in the early stage in order to fast online function buried a lot of pits, especially the performance pit, to the extent that can not be ignored.

But pit, well, or need a little bit of posterity to fill up, so so this “slightly slightly” difficult task naturally fell on me to take over the small program, then began the small program center performance optimization road.

Performance optimization was scheduled for q3, and after a series of “magic moves”, FMP of small Program center was reduced from 2100ms to 1300ms now. For small program performance optimization also have some experience, summed up a set of methods, in the group to do the sharing, talking for two hours, but maybe talk too methodological, the group of small partners seem to listen to a fan. Even after the meeting, people still ask “What can I do to improve the performance of applets quickly??” .

In fact, there is no shortcut to performance improvement, needAnalysis, optimization, experiment, monitoring, need a little bit of accumulation and in-depth. As you learn more about your project and performance optimization, the variety of ways to improve performance becomes richer, and performance data naturally follows. Still, you might ask, “So what can I do to quickly improve the performance of applets?”All right, no more faking, I’m showing my cards. (knocks on the blackboard!) Here are some simple and effective methods that can be applied mindlessly to almost any small program. You say you won’t? Well, I put the source code to you also posted up, ~~ CTRL + C CTRL + V always bar! It’s up to you what to do.

Background to performance optimization

Before we talk about performance tuning, we need to know what performance is. When we talk about performance, we are really talking about the consistent, stable, and fast response of applications under different environmental conditions, inputs, and external factors. We don’t want users to have their requirements compromised by code writing problems. We want applications that respond quickly and switch smoothly, with no pauses or waits for users to meet their needs. In the small program, performance can converge to three indicators, FMP, white screen rate, service availability, the meaning of these three indicators will be discussed below.

FMP: First Meaningful Paint. FMP usually is the most important indicators, marks the program in the general case of application performance, high FMP illustrated application load time is longer, for the first time, that is, the user needs to wait for a long time to enter into the small program, in the process, the user may choose to quit, FMP low shows that users can quickly into the small program, To the user’s feeling is fast, reduce the user waiting time.

Blank screen rate: after the user triggers the page opening and no page is drawn after a certain period of time, the blank screen is regarded as blank screen. Blank screen rate = BLANK screen PV/small program cold start PV. Bad rate is usually extreme cases of application performance, such as when there is no network, weak network, the back-end without return or return error behavior, although in most cases cannot be useful information to users, but need to be out of the strategy to prevent the user can not get feedback, if not get feedback from users will be considered a program has a problem, he won’t go to consider environmental problems, You don’t debug, and you might lose a user.

Service availability: includes

  1. HTTP request access failure rate: HTTP request access failure rate = Number of failed requests/Number of requests.
  2. JSError: JS error that occurs when a small program is running.

Service availability represents the application performance in the case of errors. The errors can be simply divided into two types according to the source. One is the server-side error, which is the specific performance of HTTP request failure, and the other is the front-end error, namely JS error. These errors may not affect anything, or they may be serious enough to cause an exception that the program cannot run, and need to be analyzed on a case-by-case basis.

You can be inDeveloper platform - development management - Operation and Maintenance center See the details of these three indicators. We can see a white rate and service availability actually sign the application of stability and error/exception scenarios, and FMP, is the most intuitive under normal business scenario description small program performance indicators, here we will revolve around how to “how to reduce the applet FMP talk about ascension” SanBanFu “small program performance.

The first plate axe – break off, reduce the size of the small program package

As we know, small program in the release of the first local code package, and then uploaded to the server, users in the use of our small program will first download the code package, and then host the small program framework in the APP [TOdo, small program core is what means??] Will render according to the code package. We can’t control the user’s network, but we can control the size of the code package. Reducing the size of the code package is one of the simplest and most straightforward ways todo this (todo, arguably, many developers do this, but it doesn’t work).

Delete resources that can be deleted, but compress resources that cannot be deleted

When the user opens the applet, they only see one page, so we can delete all the other pages and keep this one page, and then the FMP can go down.

You can’t do that unless the job doesn’t want it…

But the idea can be borrowed. In fact, if your applet goes through multiple iterations and goes through different developers, you may find that the applet features get better and the package size gets bigger, but are these pages and features really necessary? inDeveloper platform - Data analysis - behavior analysis - page analysis - page views You can see the traffic on each page of your applet,For most of the small program, the flow is only concentrated in a few pages, some pages have no flow at all, then these pages without flow and function can also be removed from the small program? B: Sure.

Unusable pages can be deleted, and unused resources can also be deleted from small packages, including custom components, NPM packages, CSS, and images.

In the process of intelligent applets development, it is often necessary to introduce image resources. If images are not used properly (too many and too large images), they will consume more system resources during loading, which will affect the performance of the entire page, so it is important to optimize the images well. 【 todo, this words is not necessarily appropriate, can see the smartprogram.baidu.com/docs/develo… this article illustrate the update: has been changed to “in the process of intelligence of the development of small programs, often need to introduce image resources. If improper use pictures too much (too much), the load will consume more system resources, which affects the performance of the whole page, therefore completes the optimization is very important. “), in the small package images with small package download, and these pictures can actually on static resource on the server, small program code using image address directly. If you need images in particular, don’t forget to turn on image compression in the Applet developer tools – Project Info – Local Configuration – Upload code.

Separate the pages with a high proportion of entry pages into the main package and the other pages into sub-packages

The subcontractIt is a method to reduce the package size provided by small programs. Developers can divide smart small programs into different subpackages, which are packaged into different subpackages during construction and loaded by users as needed when using. Suggestions in accordance with theDeveloper platform - Data Analysis - Behavior Analysis - Page analysis - number of entry pages To subcontract in descending order, put the pages with more entry pages into the main package, and other pages can be subcontracted appropriately.

It should be noted that after subcontracting, the path of the page will also change. If some pages have done promotion activities before, in order to prevent users from finding the page, it can be usedCustom Route”Maps the original address to the new address.

Second batchet – save data, skillfully use cache with official capabilities

To show the first screen quickly was our goal, and to show the first screen quickly, some things had to give up, some things had to be compromised. Using official performance tuning methods, while not elegant, is a great way to improve performance. Caching, the strategy of trading space for time, is really useful in terms of performance optimization.

Use prelink, use onInit

prelinkJust go to developer Platform – Development Administration – Settings – Development Settings – Server ConfigurationConfiguration, you can get 200ms upgrade, this is the official sword to you, do not need to see you. Its principle is to establish TCP connections in advance and reuse TCP connections. Note that the request address is configured to support HEAD requests.

OnInit () : onInit() : onInit() : onInit() : onInit() : onInit() : onInit() : onInit() : onInit() : onInit() : It’s that simple.

/ / modify before
    onLoad() {
        this.getPageData();
    }
/ / modified
    onInit() {
        if (!this.onInitLoaded) {
            this.onInitLoaded = true;
            this.getPageData(); }},onLoad(options) {
        if (!this.onInitLoaded) {
            this.onInitLoaded = true;
            this.getPageData(); }}Copy the code

Cache API-side capability

API side ability is a small program to provide different from ordinary web application function, these functions makes it easier for developers to implement rich application, but the ability is actually have the consumption of performance, compared with ordinary js statements to carry out slowly, in order to smooth the difference, some don’t often change ability of API end result can be cached, actually Fetch multiple times directly from our cached data.

const cached = swan.getStorageSync('apiResultCached') | | {};const promiseCache = new Map(a);const MAX_CACHE_TIME = 1000 * 60 * 60 * 24 * 7;
// Cache methods
function memorize(fn) {
    const apiName = fn.name;
    return function () {
        if (cached[apiName]) {
            if (Date.now() - cached[apiName]['__timestamp'] < MAX_CACHE_TIME) {
                return Promise.resolve(cached[apiName]);
            }
            cached[apiName] = null;
        }
        let promise = promiseCache.get(apiName);
        if (promise) {
            return promise;
        }
        promise  = new Promise((resolve, reject) = > {
            fn().then(res= > {
                cached[apiName] = res;
                cached[apiName]['__timestamp'] = Date.now();
                swan.setStorage({
                    key: 'apiResultCached'.data: cached
                });
                resolve(res);
            }).catch(e= > {
                reject(e);
            }).finally(() = > {
                promiseCache.delete(apiName);
            });
        });
        promiseCache.set(apiName, promise);
        return promise;
    };
}
function getSystemInfoAPI() {
    return new Promise((resolve, reject) = > {
        swan.getSystemInfo({
            success: res= > resolve(res),
            fail: err= > reject(err)
        });
    });
}
Swan.getsysteminfo = swan.getSystemInfo = swan.getSystemInfo = swan.getSystemInfo = swan.getSystemInfo
export const getSystemInfo = memorize(getSystemInfoAPI);
Copy the code

Cache page master data

If the data on the Page is static, it can be written directly to the data in the Page, but in most cases, the Page is partly static structure and data that can be rendered in the front end, and partly data fetched from the back end interface. The first screen data obtained from the back-end interface can be cached in the storage, so that the page can be obtained from the storage when it is loaded for the second time, and the page data can be updated after the request is returned. Note that in order to display the page faster, we only cache and load the data visible on the first screen.

// Get page data from storage
swan.getStorage({
    key: 'pageData'.success: res= > {
        // Render the page with cached data if there is a cache and the asynchronous request does not return
        if (res.data && !this.requestBack) {
            this.renderPage(data); }}});// Asynchronously request page data
getPageData().then(res= > {
    this.requestBack = true;
    // Render the page based on the latest data after the request returns
    this.renderPage(res.pageData);
    // Cache page data to storage
    swan.setStorage({
        key: 'pageData'.data: res.pageData
    });
});
Copy the code

One problem with this is that the page data may not always be the latest data when it is loaded, and the latest data will refresh the page when it is retrieved from the request. Therefore, if your application is very real-time, it may not be suitable to use this method.

Third plate axe – Light render, render only what is necessary

In the process of applets loading, the logic code and rendering code are separated, and are carried out by different threads.Slow threads can slow down the entire load, so when your logic is already running, consider whether there are ways to improve on the render level.

Reduce rendering overhead

Applets themselves provide a variety of uses, including custom components, dynamic libraries, filters, SJS, etc. These features improve the efficiency of our development, but on the other hand, the variety of features can introduce new performance consumption traps. You need to find a balance between efficiency and performance. What uses have limited efficiency gains but significant performance costs? This needs to be combined with the practice of your own business, but on pages with a high percentage of FMP, these features need to be taken very seriously.

In addition, you need to pay attention to reducing the special properties and events of the View and Text components, which is easy to overlook. Although the performance cost of a single use is limited, there are too many places to use the View and Text components to make a qualitative difference. This is especially true for custom components, because custom components may be used many times (such as list items, or even hundreds or thousands of times), and the performance cost of a low-performance custom component can be multiplied.

// Modify the view before using the style attribute<view style="height: 20rpx;">Hot list</view>Title {height: 20rpx; }<view class="title">Hot list</view>
Copy the code

Split screen rendering

If we load a list that is longer than one screen, and the user doesn’t see all of the list, but only the first few items of the list, we can load only the first few items of the list and then load the rest as the user swipes. Similarly, when rendering the page, we can also perform data segmentation in the first setData, only set the first screen visible data, delay setting non-first screen data.

// appList gets page data from the back-end interface. Active is the currently visible TAB index
// firstLoadAppList is the calculated first screen data
const firstLoadAppList = appList.map((item, index) = > {
   return index === active ? item.slice(0.10) : [];
});
this.setData({
   appList: firstLoadAppList
}, () = > {
   // Complete data records can be loaded later
   this.appList = appList;
});
Copy the code

Cancel the skeleton screen using progressive loading

Skeleton screens are a mechanism provided by applets to optimize the user experience, but any rendering has a cost, as does skeleton screens. Writing complex structures and even animations in skeleton screens is not conducive to fast and meaningful page loading. Of course, skeleton screens do make it easier for users to perceive a page loading, so there’s a balance to be struck between seeing a page loading first and seeing meaningful content faster. One recommended solution is:

  • Use the official skeleton screen, but simplify the skeleton screen frame, reduce the use of styles and animations
  • In real page rendering, set the background color and height for each section, inPagedataSet the default value in, has not been done for the first timesetDataRender the frame of the page. This way, when the page data comes in, you just fill in the values in a specific part.

Afterword.

Welcome to ask performance-related questions in the small program developer community, and also welcome to follow me on Github. I will update some front-end related articles from time to time. If you want to discuss performance related issues with me in more depth, please send me an email.