background

When we used taro and @freud/http (internal project of the company, secondary development based on axios), we found that there were many useless packages in the build product, resulting in the product becoming about 150kb larger.
After some searching, I found that the taro applet cannot parse the browser module and other fields in package.json, and @frued/http needs to support both web and applet environments, and there is a browser attribute in axios:

 "browser": {
    "./lib/adapters/http.js": "./lib/adapters/xhr.js"
  },

Therefore, when axios is introduced into taro, lib/adapters/http.js will also be packaged in. There will be many dependent packages such as zlib in http.js, which will lead to the problem of the above package being too large .

Solutions

First, we can locate the location related to the axios source code:

 if (typeof XMLHttpRequest !== 'undefined') {
    // For browsers use XHR adapter
    adapter = require('./adapters/xhr');
  } else if (typeof process !== 'undefined' && Object.prototype.toString.call(process) === '[object process]') {
    // For node use HTTP adapter
    adapter = require('./adapters/http');
  }

Under normal circumstances, in the web environment, ./lib/adapters/http.js will be replaced by ./lib/adapters/xhr.js so the above code will become after packaging.

 if (typeof XMLHttpRequest !== 'undefined') {
    // For browsers use XHR adapter
    adapter = require('./adapters/xhr');
  } else if (typeof process !== 'undefined' && Object.prototype.toString.call(process) === '[object process]') {
    // For node use HTTP adapter
    adapter = require('./adapters/xhr');
  }

After we know what the build product should look like under normal circumstances, let's look at our current build product.
Because @frued/http is built based on rollup, the product is as follows:
The reference to axios is reserved in index.js var axios = require('axios') , while the corresponding lib/default.js is still referenced adapter/http
Figure 1
Jgh5vobkfj.png
Figure II 7239D0F0-9C7C-47BA-A688-A390371FEFB6.png

So far, we have roughly two directions to solve the problem:

  1. Build tool tweaks and optimizations
  2. Modify the source code to avoid redundant references

specific plan

So the corresponding solutions are:

  1. Upload axios to the private library and delete the relevant references to http.js
  2. Using the patch mechanism of the npm package, modify the source code of axios in @freud/http and delete the relevant references to http.js
  3. Split @freud/http into 2 npm packages, corresponding to the web environment and the applet environment respectively
  4. Use webpack instead to package @freud/http
  5. Introduce rollup plugin

1-3 is very simple, no need to go into details. Let’s talk about the fourth point first, why using webpack can solve this problem.
In order to better perform tree shaking in rollup, only references to dependencies are kept, instead of directly packaging the code of dependencies into index.js (see Figure 1). So @freud/http When axios is introduced, the code of axios still retains the reference to http.js, only when the actual web project runs, the browser field takes effect, then http.js is replaced by xhr.js.
But when webpack is built, the browser field in the dependency package will be parsed by default (see the figure below)
image.png
At this point, http.js will be replaced by xhr.js. Because of the different handling of dependent packages, webpack builds can solve this problem.
The fifth point, still under research, there is a build tool bili based on rollup for secondary encapsulation to solve this problem.

end

Because @freud/http is a monorepo project, it is built using rollup uniformly. If all packages are built with webpack instead, the cost is too high. Based on this, I chose to add webpack to the subpage for secondary construction, that is, after rollup builds the subpackages in the @freud project, and then execute the webpack build command in @freud/http to rollup The build product of lib/index.js is built again with webpack. This can avoid writing the babel configuration again in the subproject, so that the basic build configuration of all subpackages is the same.


notself
134 声望13 粉丝