Author: Gu Gu Man – The Underworld

preface

In web development scenarios, reducing code size is one direction of performance optimization, but it’s not so specific. However, in the small program scenario, because the size of the main package is 2M and the total package is 16M in the upload stage of the code package (wechat official is adjusting the upper limit of the total package to 20M in the internal test recently), if the size exceeds that, it will face the risk of failure to release, so the optimization of the volume of the code package becomes particularly important. As the big entrance of wechat shopping, the homepage of Jingxi small program bears a large amount of traffic and has many modules with complex functions. Besides, it needs to share 2M of main package space with other core businesses and public components. Therefore, the work of reducing the code package is constantly going on, otherwise it cannot meet the rapid growth of business. This article will be combined with the previous optimization strategy and a recent practice of slimming, to share the small program code slimming experience and thinking.

Common thin body way

Jingxi home page project is a well-optimized project. There have been good practices for common optimization measures. Let’s first review the common optimization strategies:

  1. Code subcontracting: Splitting relatively independent pages and components into subcontracting can solve the volume limitation problem of the main package;

  2. Dependency analysis: Remove unreferenced pages, components, and other files

  3. Avoid using local resources: Except for the bottom image, use URL as far as possible. Base64 is essentially encoding information into long strings, which will take up a lot of space, so it is not recommended to use it.

  4. Compress and clean comments for all types of files, including: JS, WXML, WXSS, JSON;

In addition, jingxi home page team also optimized the Taro development scenario as follows:

  1. Analyze the frequently repeated code for each file after compilation (such as Pollyfill code for compatibility), split it into common files, and replace the original references for sharing.

Standards and Tools

Before we begin the formal slimming practice, let’s clarify the code package size metrics and statistics.

The size of the code package is subject to the upload code of the small program. The 2M limit means that the size cannot exceed 2,048 KB.

From a message transfer perspective, compression tools like Gzip can do a lot of information coding optimizations, so some duplication is acceptable, but since the goal is to overcome applets upload limits, it’s only the size of the code package that matters.

The most recent package size can be seen in developer Tools – Details – Basic Info – Last preview or last upload, and the optimizations described in the rest of this article aim to reduce this size.

But the code upload is slow to generate templates, and it would be inefficient to count volume changes every time based on the data here.

Without changing the project configuration, we can use the file size of the code directory as an indirect reference for change. How to calculate file volume conveniently? Here I use tree-CLI, which provides parameters to print a list of code files with dimensional statistics and sorting functions:

NPM install -g tree-cli // Target directorycdTarget-directory // The output file is size-analysis.md tree -s --sort= size-o size-analysis.mdCopy the code

The list content format is as follows:

.├ ── [500].Index.Index.Index.Index.Index.Index.Index.Index.Index.Index.Index.Index.Index.Index.Index.Index.Index.Index.Index.Index.Index.Index.Index.Index.Index.Index.Index.Index.Index.Index.Index.Index.Index.Index.Index.Index.Index.Index.Index.Index.Index.Index.Index.Index.Index.Index.Index.Index.Index.Index.Index.Index.Index ── [ 4000] child │ │ ├ ─ ─ [1000] index. The js │ │ ├ ─ ─ [1000] but WXML │ │ ├ ─ ─ [1000] but WXSS └ ─ ─ └ ─ ─ └ ─ ─ [1000] index.json 6500 bytes usedin 2 directories, 8 files
Copy the code

Thin body practice

Said in front of the Beijing xi home page optimization measures are doing very well, the following is some less to share common way of optimization, optimization of space have greatly small, want to optimize small program code package, suggested to try to finish, the optimized plan for the mentioned above such gains from the most obvious, and then to see the next mentioned the way ~

Global font and color sharing

Inheritance styles, such as font and color, are inherited from outside the component to inside the component, according to the applets documentation.

By analyzing the current situation of the project, we usually put the font definition in the public CSS file. With the introduction of the page or component into the public CSS, font will also be repeatedly introduced. We can change the definition of font only in app.wxSS, and eliminate the introduction of components and pages, so as to reduce the size of the overall code package.

Regarding the 1% reduction in the volume of this home page project, it is estimated that the entire project still has about 20KB of FONT definition to clean.

Similar optimizations can be made if there are global color definitions.

Second, the use of style completion function

As a Web developer, we are familiar with the -webkit- prefix, and usually use autoprefixer for style completion at compile time to fit different browser kernels.

The applets developer tool also provides the ability to style completion: Details – local Settings – you can check “style completion when uploading code”

Is this completion any different than what we do at compile time?

The key is the timing of the implementation: if it is before the local template is uploaded, it should have the same effect as the completion we compiled. If you are uploading the template, you may be able to reduce the size of the complete content.

Combined with the small program code package transfer process and style completion time, there are probably the following three situations:

Stage I completion:

Stage 2:

Or stage three:

To verify the conjecture, let’s do an experiment and compare “project compile complete style + Developer Tools set style complete” vs. “Project compile complete style + Developer Tools set style complete”. The template volume statistics are as follows:

This shows that the former is 58KB less than the latter, indicating that the style completion provided by the developer tool is not done in stage 1, otherwise the template size should be basically the same as our own compilation completion.

Then, you can happily remove compile completion and use the capabilities provided by the applets developer tools.

However, there will be a small problem with this change. The styles in the developer tool are not completed, and some styles will have some problems. The test found that the mask-border-source is invalid, while the corresponding real machine has no problem because the style completion has been added. To avoid preview misunderstandings, it is recommended that unsupported styles be manually prefixed with -webkit- to ensure that development and real machine performance are consistent.

Watch out Sass!

Tools like Sass/Less make CSS writing smoother, and the introduction of functions and variables gives CSS a little more of an engineering feel. But have you ever looked at the compiled implementation of Sass?

// a.css, as the referenced party
.banner {         // Style definition
	color: red;
}
$COLOR = red     // Variable definition (function definition is similar)

// b.css as the user
@import 'a.scss';
.banner_wrapper {
	background: white;
	color:$COLOR;
}
Copy the code

B. sass:

// references to the A.s CSS disappear and the content is consolidated into the file

.banner {              // style definitions in the CSS are copied in
	color: red;
}
.banner_wrapper {
	background: white;
	color:red;           // Variable definitions are replaced by values
}
Copy the code

The question here is: do we need the banner to be copied in

To avoid introducing more unwanted style definitions, there are several directions:

  1. Split by function. Style definitions in CSS are introduced as needed.

  2. Using the @include syntax, change the definition of the banner to a variable and import it as needed.

In the small program scenario, WXSS syntax supports @import, which implements a very weak version of modularity, allowing us to add another Angle to solve the above problem:

  1. Bypassing sASS compilation, use the applet’s @import syntax to introduce the required style definitions. (For how to bypass SASS compilation, consider using comment fragments, or whitelist filter recognition.)

4. Remove redundant code in multi-terminal scenarios

The first page project is developed using Taro, which needs to adapt H5/ wechat mini program /QQ mini program and other multi-terminal scenarios. Using the environment variable capabilities provided by Taro, multi-terminal difference processing can be realized within the methods, such as the following paragraph:

init(){
  if(process.env.TARO_ENV === 'weapp'{
     // wechat applet logic
     this.initWeapp()
  }else if(process.env.TARO_ENV === 'h5') {// H5 page logic
     this.initH5()
  }
}
initWeapp(){... }initH5(){... }Copy the code

Small program side packaged code:

init(){
	this.initWeapp()
}
initWeapp(){... }initH5(){... }Copy the code

However, the environment variable approach does not handle the initH5 method definition, resulting init being packaged as well.

Therefore, we need more powerful difference packaging: Jingxi home page uses the conditional compilation capability provided by the internal WXA-CLI tool to realize the difference packaging at the level of code fragments by annotating paragraphs and marking multi-terminal content. Details are as follows:

init(){
  if(process.env.TARO_ENV === 'weapp'{
     // wechat applet logic
     this.initWeapp()
  }else if(process.env.TARO_ENV === 'h5') {// H5 page logic
     this.initH5()
  }
}
initWeapp(){... }/* wxa if:type=='h5' */Marks the start of the H5-side codeinitH5(){... }/* /wxa */Marks the end of the commentCopy the code

Packaged code:

init(){          / / the weapp
	this.initWeapp()
}
initWeapp(){... }Copy the code

InitH5 is gone and the code is thinner

5. Organize the log

Do you have long logs in your project for debugging purposes, like this:

console.log('==============xx interface abnormal ============')
Copy the code

After testing, the home page code file contains 5KB of content is log statement, can try to optimize:

  1. Remove debug logs in time

  2. The information class log conventions a shorter format

Six, good coding strategy

Is there a logical requirement that can be met in a shorter and more elegant way?

Code analysis is a complex topic, so let’s write a simple way to draw a clear conclusion

Data access and intermediate variable issues when formatting data

function format(list){
 let result = []
 list.forEach(item= > {
    const {
      a,
      b,
      c: f,
      d,
      e,
    } = item

    result.push({
      a,
      b,
      f,
      d,
      e,
    })
  })

  return result
Copy the code

You can use lodash’s pick method to rewrite:

import { pick } from 'lodash/pick'

function format(list){
 return list.map(item= >({
 	...pick(item,'a'.'b'.'d'.'e'),
 	f:item.c
 }))
Copy the code

Seven, style naming compiler optimization

Jingxi home page project due to H5 end mix old project, in order to avoid class name conflict, using the shape of block-name__Element – BEM naming rules. Further in development, some common names like navbar-content__item occasionally collide, and the class names get longer to avoid collisions, while the size influence of the small program code package grows.

To resolve naming conflicts, it’s a good idea to hash class names, and CSS-Modules is a full-fledged plug-in that can configure rules to compile a “filename + content dependent” hash for style names.

However, if you look at its implementation, you will find that the impact on code size is not good. Here is a compiled example:

Import style from '. / index. The module. The map. The SCSS. Js' / / js file, increase the introduction of a jsMap < view the className = {style.css. Banner} > < / view > / / WXML file, Hash {xx} // WXSS file. Class name hash {xx} // WXSS file. Class name hash module. Exports = {banner: Hash} // A new map file is added to map the original name to the hash name. The added size is the original class name +hashCopy the code

Calculate the overall content change:

  1. Js add map statement: add a line of code

  2. < span style = “font-size: 14px! Important; line-height: 20px! Important;”

  3. Total of map files and WXSS files: Map contains N original class names and hash mappings. WXSS now contains N hash mappings. Subtract the original N original class names, and the total increment is 2N hash mappings

As you can see, the introduction of CSS-Modules causes the overall code size to increase.

Does this new map file look familiar?

When we compress the JS file, we have a sourceMap file, which retains the original name and code location for easy positioning and debugging.

The map file implemented by CSS-Modules, in my view, works just like the named index in sourceMap. It doesn’t seem to be useful for the code logic except to keep the reference information of the original class name. In size-sensitive scenarios, you can consider removing the map file. It would be nice if it could be implemented like this:


/ / import style from '. / index. The module. The map. The SCSS. Js' js file to cancel the introduction of the map

/ / WXML file
<view className="hash"></view> // Evaluate and replace style.banner with // WXSS file.hash {xx} /Module. exports = {banner: hash} // Delete don'tCopy the code

There is no relevant processing online search, can only make their own wheels.

Because the current main purpose is to slim down the mini program code, H5 terminal file processing and mini program also have some differences, so for the time being, I only create a plug-in for mini program scenarios, named “P-CSS-Modules”. The github address is here: github.com/o2team/weap…

The general idea is:

  1. Complete the implementation of the small program CSS – Modules

  2. On this basis, the related simplified logic of map removal is carried out

  3. Further, to account for the default style isolation nature of the applets component, the naming of hashes is shortened again to monoalphabetic.

If you only develop the small program side, you can use this to achieve the small program style naming related code thin, and for Taro’s multi-terminal scenario, you can also solve the H5 side naming conflict problem.

Do you realize the effect of “APP-cS-modules”?

/ / js file
let style = {}    // Don't reference map, add compatibility to introduce style for non-specification

/ / WXML file
<view className="a"></view> // Evaluate and replace style.banner with monogrammed // WXSS file.a {xx} /Module.exports = {banner: hash} / because of applet component style isolation, we can shortest class name module.exports = {banner: hash} // Delete don'tCopy the code

The gXCME homepage project uses CSS-modules writing method through reforming components, and appellates P-CSS-modules compilation. The relative size of the code is reduced by 10%, which is still very effective. Interested students can try it out.

conclusion

About code slimming, I would like to mention the concept of entropy in informatics: entropy reflects the disorder degree of information. The lower the disorder degree of a piece of information is, the lower its entropy value is and the larger the space can be compressed. The higher the disorder, the higher the entropy and the smaller the space that can be compressed. The process of data compression, or code slimming, is to optimize how information is stored to approximate its true entropy.

From this point of view:

  • “Font and color global sharing” and “use of style completion function” is borrowed from the ability provided by the small program, the amount of information unchanged;

  • “Beware of Sass”, “Redundant code removal for multi-terminal scenarios” is to reduce unused information;

  • “Clean log” and “Style naming compiler optimization” are concise and effective messages;

What seems most difficult to categorize is “good coding strategy,” which is the sorting and integration of information during the coding phase, or condensed and effective information.

The above is the main way to thin the code of the Beijing Xi home page project, in addition to the deletion of files, integration of public files these physical work, I will no longer be wordy. Through the above way, Jingxi home page code in the original optimization on the basis of good, to achieve another 30% weight reduction goal, I hope to bring small program developers valuable information and thinking.

The resources

[1] CSS Modules: github.com/css-modules…

[2] the Tree – the Cli: github.com/MrRaindrop/…

[3] Small program engineering exploration: mp.weixin.qq.com/s/_NSJTQ-4-…

[4] WeChat applet limit 2 m thin body skill and method a: blog.csdn.net/wlanye/arti…