preface

For Internet products, the first impression is the startup speed of the application. Although the user won’t feel much if it starts fast enough, if it starts slow it will be detected and challenged. In summary, fast is the way to go.

The optimization of startup speed can be divided into first startup speed optimization and second startup speed optimization. For different types, the corresponding optimization scheme is also completely different. How to determine the direction and priority of optimization is based on the specific business scenario.

The business scenario

It would be unprofessional to talk about optimization without talking about business scenarios.

This optimization practice mainly relies on the auto insurance business of Weinsurance.

As we all know, car insurance is generally for one year. So the frequency of visits by auto insurance users is very low, once a year. Secondly, due to regulatory requirements, users must first complete the real name authentication before insuring car insurance; The vehicle to be insured can only be added after the certification is passed. Therefore, if a user wants to complete the insurance, he must go through the steps of real-name authentication, adding vehicles, quoting, paying and completing the insurance.

In addition, in order to optimize the problem of low user access frequency, the platform usually provides some necessary services for car owners. To increase user activity.

It can be seen that the business matrix of Micro auto insurance is roughly as follows:

Compared with the car owner service, the performance of the main process is more important, after all, the process involved in the transaction is the key. Therefore, this summary is also based on the optimization practice of the main process.

To optimize the direction

The vast majority of owner users have only one car. So there’s only one chance a year to buy auto insurance. For such a low-frequency product, every time a user comes in, it’s a new UI, a new code. It is equivalent to the first start every time, the first start speed is extremely important. This is also the main direction of this optimization.

We refer to the RAIL performance model goals proposed by Google.

  • User-centered; The ultimate goal is not to make your site run fast on any particular device, but to make most users happy.
  • Immediate response to users; Confirm user input within 100 milliseconds.
  • When setting up animation or scrolling, generate frames in 10 milliseconds or less.
  • Maximizes idle time on the main thread.
  • Keep attracting users; Render the interaction within 1000 milliseconds.

In summary, our first optimization principle is to ensure that the vast majority of users can access our application quickly.

The preparatory work

There is one more important piece of preparation before you start tuning your performance. That is to collect baseline data in advance. Benchmark data is a good way to measure your optimization.

Although the wechat public platform provides charts of the startup time and download time of small programs, the original data cannot be provided, which is not conducive to detailed analysis. Therefore, the data provided by the self-built log reporting system is used in this performance optimization.

It’s not enough to identify performance metrics and get relevant data.

Because the actual network environment is very complex, the original data collected is very rough, the same code, the same configuration, in different network environment and mobile phone, the loading time will vary greatly. Therefore, certain processing must be done to collect all kinds of extreme data before they can be analyzed:

Common processing (index calculation diameter) is mainly as follows:

  • Average: The most straightforward idea is to calculate the average of all the data. However, the average will be too large due to some extreme values, and the data will fluctuate greatly. Therefore, the average is not suitable as a reference index.
  • 95th quantile: Rank all the data from smallest to largest, take the 95th position, and use this value as our performance indicator.
  • Truncated average: Again, put all the data in order, remove part of the data at the end, and then take the average. This value will be relatively stable and suitable as a reference index.

In combination with the first optimization principle mentioned above, the obvious truncation mean is the best choice for calculating aperture.

For example, if we promise to ensure that 90% of our users load the applet within 1000ms, then we only care if the first 90% of our users load within 1000ms.

Obtain the average loading time data of the top 50%, 80% and 90% users who consume less time by truncating (the optimization effect of loading time of these three types of users will be subsequently analyzed horizontally)

After processing the data, the performance analysis can be classified as follows:

  • By mobile phone system (Android, iOS)
  • Classified by network environment (WIFI and 4G)

The following is the loading time of auto insurance subcontracting without distinguishing mobile phone system under 4G network collected (as the baseline data before optimization) :

practice

Since applets provide many basic apis, UI libraries, and this part of the code is the dependence of each applets. So when the code is initialized, this is the first one initialized, and the rendering process looks like this:

Compared to the traditional Web, we can optimize in many ways. For example, resource loading sequence (image lazy loading, CSS pre-loading, JS post-loading, etc.), using build tools to achieve on-demand loading, etc. However, the underlying logic of the small program is relatively closed, and we cannot deeply participate in it. Therefore, to optimize the loading performance of the small program, the best and most effective solution is to optimize the size of the small program code package.

There are several ways to optimize code package size:

  • Remove unused code
  • Implement code to load on demand (in the case of applets, subcontract loading)
  • Remove image resources from the applet (because the applet download uses gzip compression by default, rather than text compression is less efficient)
  • Simplify JavaScript and try to avoid complex calculation in the front end (try to transfer JS logic to the back end or use Nodejs middle platform to complete this part of calculation work, which is also conducive to the subsequent expansion to multiple platforms)

Remove unused code

As auto insurance is the first product launched by Weinsurance, it has gone through numerous iterations, and it is inevitable that there will be businesses or functions that have gone offline. This part of the code is usually in pages, so it can be found with PV data.

PV data, by the way, how to build a log reporting system. Since each Page of the small program has a complete life cycle, the onLoad method of the Page will be triggered when entering a new Page. At this time, the PV data statistics of the Page can be completed by reporting the information of entering the Page to the background service.

There are two ideas for how to implement redirection handling of error paths:

  1. Routing capabilities provided by applets (e.gwx.navigateTo), which is emitted when the incoming URL does not existfailMethod, at this time infailWe can deal with it.
  2. usewx.onPageNotFoundMethod, but there are certain compatibility issues.

Auto insurance subcontracting reduced from 1100+KB to 900+KB (18% reduction) after removing unused codes

Code loads on demand

Ideally, visiting users should download only the resources they access and wait until they need them. In this load – on – demand scheme, small programs are handled by code subcontracting. However, because subcontracting and subcontracting can not reference each other’s resources, can not reuse the code, so the separation of subcontracting will inevitably lead to the decrease of the efficiency of development. Therefore, the balance between performance and efficiency should be grasped when subcontracting.

Therefore, we propose a subcontracting split principle based on UV and access path.

Combined with the log system, we found that the real name authentication page of auto insurance is a large UV user, and the logic of real name authentication is similar to the logic of adding vehicles and editing vehicles, including vehicle management logic and components. Therefore, the code similarity of this page surface is relatively high, which is suitable for disassembly into A subcontract. Finally, the pages of real-name authentication and vehicle management are disassembled into subcontract A of new user.

Secondly, through the observation of page funnel data, it is found that most users only visit the main process page: auto insurance home page, quotation page, payment page, policy details page. As for the branch processes such as the adjustment scheme page and vehicle list page, only a small number of users will access them. Therefore, the pages of the main process are divided into the main subcontractor B, and the pages of all other branch processes are divided into another subcontractor: other subcontractor C.

Finally, the subcontracting of auto insurance is divided as follows:

  • New user subcontracting A including real-name authentication and vehicle management process (200+KB)
  • Main subcontracting including main process B (400+KB)
  • Other subcontracting including branch processes C (100+KB)

For new users (who have not completed real-name authentication), different paths are distributed through pre-detection of real-name status, so that new users can only load subcontract A of new users first, and at the same time, the main subcontract B is preloaded. Therefore, for new users, the new user subcontract A of 200+KB was loaded for the first time. Compared with the complete subcontract of 900+KB loaded before optimization, the subpackage size of the loaded small program was reduced by 78%.

For old users (who have completed real name authentication), new user subcontract A is no longer loaded, while other subcontract C is preloaded at the same time, so the size of loaded applets subcontract is reduced by 56%.

Simplify the JavaScript

This part of optimization is similar to traditional Web development optimization.

Once the code package is downloaded, business code injection is completed. In this case, the JavaScript engine has to parse/compile JavaScript, which is also the most time-consuming operation of the JS engine. As you can see from Chrome Developer Tools, the yellow part is the part that takes the most time to parse/compile:

Due to historical problems, some complex data need to be pieced together by the front end (such as the calculation of renewable vehicles). By moving this part of the logic to the back end, the JavaScript code is further simplified, making only basic presentation transformations to the final data.

Since this practice did not go into this aspect of optimization, it is not detailed description of the effect of this optimization, there will be another opportunity to talk about the opening article in detail.

Problems encountered

In the process of this optimization practice, we have encountered many problems, and share our solutions with you.

The first problem we encountered was the reference to the component.

Because of the limitations of applets, components cannot reference each other across subcontracting. In order to reuse components across subcontracting, components must be placed in the main package of applets, and the code of the main package is common across businesses and cannot be added arbitrarily. Therefore, this problem should be taken into account when splitting subcontracting.

Secondly, it is the reference problem of JS public library.

Originally in the same subcontract, through the relative path can be introduced. However, after splitting into multiple subcontracts, JS cannot be directly referenced. At this time, we need to change ideas, such as: mount the JS public library to the global variable global; Or copy code to other subcontractors (not directly, of course, but via gulp or Webpack). Or put the public library on the main package.

There are even more headaches, directory changes lead to the problem of route hops.

Because the small program subcontracting mechanism requires each subcontracting to be in a directory. Therefore, splitting and subcontracting will inevitably migrate files, and the jump of the small program and the strong coupling of file directory, file path changes lead to jump path changes. Therefore, the jump path of all involved pages should be changed.

At this point, consider forward compatibility, such as pushed template notifications. Therefore, the encapsulation of route hop is extremely necessary.

The effect

After the above cocooning and stripping, finally waiting for the online time, you can see that the optimization effect is very obvious:

By horizontal comparison of users of different categories, we can see the improvement of various users more clearly:

For the faster top 50% of users, it also increased access speed by nearly 50%.

This optimization ensures that 90% of users can complete the loading of small programs within 2000ms.

The follow-up to optimize

We still have a few plans for the next optimizations:

Take full advantage of the predownload and subcontract features provided by applets. If pre-download is not set, the user will have to wait for the download of the subcontract when jumping to another subcontract page. For more impatient users, will think card machine, eventually lead to the user jump out. (The only limit for the predownload of small programs is that the sum of the subcontracting size of the current subcontracting and the predownload subcontracting size cannot exceed 2M. If so, you can consider splitting the subcontracting again.)

Simplifying WXML classes. Class selectors are the most common style selectors, and classes tend to get longer and longer as pages get larger. However, in applets that do not support DOM manipulation, class’s main role is mainly style injection. So you can script the same WXML and WXSS classes into a single, short name.

Node.js intermediate platform transfer part is used for calculation. The JavaScript code is further simplified, which is conducive to further optimize the loading performance of small programs. Secondly, there is also an extension to other platforms such as H5.

conclusion

Although it seems that the development and publishing methods of wechat applets are very different from traditional Web. But the underlying operation is similar, so you can take ideas for optimization from traditional Web optimization practices.

Some of the optimization practices mentioned in this article are very customized and handled in a particular way for a particular business scenario. There is no doubt that as the business evolves, so does the code, and this requires constant optimization to make the user experience better and better.

Thank you for reading. If there are any mistakes, please correct them. Thank you.