background

In the process of developing wechat mini program, as the business logic becomes bigger and bigger, it highlights some problems.

First of all, we find that the local package size has reached 4m+ in dev mode. In this case, we can no longer use real machine debugging in dev mode.

Secondly, at this time, the small program build also has about 1.8m. There are still quite a few business requirements to develop, and the package size will certainly be larger.

This is where you want to optimize the applets size. Here is my positioning process and solution to share. Although we use uni-app development, but the idea is universal, hope to give you some help.

How do I reduce the packet size

The code analysis

First, analyze where bao Da is.

Open the local code directory to see the file size. It can be found that common/vendor.js and Page,components are dominated by JS.

In build mode, code compression is already enabled, so you need to think about other optimizations. You can use the webpack-bundle-Analyzer plug-in. It can help analyze which JS modules are in Vendor.js and which modules are large, so that we can further optimize the code

With this plug-in, the following two problems were discovered.

Uni-app custom component schema compilation tree shaking is invalid

You can skip this section if you are not using UNI-app development

Code analysis showed that some modules should have been tree shaking but were packed in. Tree shaking is not working.

Again, webpack4 plus babel7. Tree shaking is fine if you don’t use uni-app and use vue-CLI Create directly. Tree shaking does not work when using uni-app to create new projects.

Modules: ‘commonjs’ is set to uni-app when the project is created. Modified tree Shaking OK for demo. But when I went back to the project and compiled it, it failed again. Continue to locate and discover a compilation problem with the UNI-APP custom component schema. Uni-app has fixed the bugs I mentioned, although it has not been officially released yet.

Of course you can do this without using uni-App’s custom component mode. Uni-app also supports template mode, but there are some development differences and performance gaps. If you are interested, read this article

Tree shaking is not supported in some libraries

Some libraries (like Lodash) don’t use import/export themselves, so WebPack doesn’t tree shaking them. We can optimize these libraries by case.

First, check to see if there is an ESM version of the library that can be replaced, such as Lodash-es.

Secondly, we can see from the code analysis that if every module of the library is in a different file and the entry file is just a unified entry, then we can load it on demand by modifying the writing method, such as

import add from "lodash/add";
import Button from 'ant-design-vue/lib/button';
Copy the code

We can also use the babel-plugin-import plug-in to unify the loading on demand for those libraries. The essence of this plug-in is to uniformly change the loading path at compile time according to the configuration, without having to modify the code manually.

If all else fails, either accept it or rewrite it and contribute to the community

Specification module development

To avoid tree shaking, we also need to follow specifications when developing NPM modules to reduce the size of packaged modules.

Support for both CommonJS and ES Modules

Our module needs to support both CommonJS and ES Module. This will satisfy both commonJS developers and tree Shaking.

How do you do that? If your code is typescript, using @sentry/browser as an example, you can compile both CJS and ESM specifications at compile time, as follows

// package.json
"build": "run-s build:dist build:esm build:bundle"."build:bundle": "rollup --config"."build:dist": "tsc -p tsconfig.build.json"."build:esm": "tsc -p tsconfig.esm.json".Copy the code

Then specify two entries in package.json and no side effects identifier

  "main": "dist/index.js"."module": "esm/index.js"."sideEffects": false.Copy the code

This way, when WebPack parses modules (parsing rules), esM directories are parsed first on demand. And tree shaking is done when no side effects are identified.

If your code itself is ES6, you can do the same

"module": "src/index.js".Copy the code

Third-party custom components

If a third-party wechat custom component is used, the reference is in a JSON file, so webpack cannot analyze the relevant file through entry during compilation, so it will not be compiled or compressed. This is where we have to deal with it ourselves. And since WebPack doesn’t handle it, tree Shaking certainly doesn’t support it, so it’s recommended that you avoid referencing components in this way.

The subcontract

Small program subcontracting is also a conventional optimization scheme.

After analysis, some of the larger pages can be divided into subpackages. If you have a single page that relies on a third-party custom component and the third-party component is large, you can also consider splitting the page into subpackages. Therefore, try to avoid placing third-party custom components in globalStyle, otherwise it will not be possible to put it into subpackages.

Do not pack large pictures

The large image in the small program, try to avoid packaging in, should be put in the CDN through url loading. We do this by loading local images at development time, automatically publishing images during CI/CD, and rewriting addresses.

How to solve the real machine debugging problem

The first step is to look at the compiled file and see that common/ Vendor.js is huge, at a whopping 1.5m. Secondly, Pages and Components also have 1.4m, which account for the vast majority of JS size.

Why are JS files so big? This is mainly because there is no compression by default in dev mode, and of course there is no tree shaking.

My choice is to modify the compile configuration and compress the JS code in Dev Mode. Native code is reduced to 2M. The preview size is reduced to 1.4m. The reference configuration is as follows:

// vue.config.js
    configureWebpack: () => {
        if (isDev && isMp) {
            return {
                optimization: {
                    minimize: true,},}}}Copy the code

This may not seem like a good solution, but it is simple and effective. Subcontracting was also considered, but it didn’t solve the huge problem with Common/Vendor.js, as the package was still large at preview time. If there are other good ways to also welcome message ~