Solve the problem that the axios package is too large in the taro applet

Solve the problem that the axios package is too large in the taro applet

background

When we used taro and @freud/http(the company's internal project, 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 it is because the taro applet cannot parse fields such as browser module 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, it will lib/adapters/http.jsalso be packaged . 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 a web environment, ./lib/adapters/http.jswill be ./lib/adapters/xhr.jsreplaced 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: Index.js retains a reference to axios var axios = require('axios'), while the corresponding axios is lib/default.jsstill referenced adapter/httpFigure 1 Jgh5vobkfj.pngFigure 27239D0F0-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, @freud/httpmodify the source code of axios in , and delete the relevant references to http.js
  3. Split into @freud/http2 npm packages, corresponding to the web environment and the applet environment respectively
  4. Use webpack instead @freud/httpfor packaging
  5. Introduce rollup plugin

1-3 很简单,不用细讲。先讲一讲第四点,为什么使用webpack就可以解决这个问题。 rollup中为了更好地做tree shaking,因此只保留着对依赖的引用,而不是直接将依赖的代码打包到index.js中(见图一)。所以@freud/http 引入axios时,axios的代码依然保留着对http.js的引用,只有到实际web项目运行时,browser字段生效,则http.js被xhr.js替换。 但是webpack构建时,会自动解析模块内容,将所有模块打包后的内容和id以key value的形式存在于构建产物的一个数组中,此时http.js就会被xhr.js替换。 故由于对依赖包的处理方式不同,webpack构建即可解决此问题。 第五点,尚在研究中,有基于rollup做二次封装的构建工具bili 解决了这个问题。

结尾

因为 @freud/http 为monorepo项目,统一使用rollup构建。若所有包都改用webpack构建,则成本太大。基于此,我选择了在subpage中添加webpack做二次构建的方式,即在rollup将@freud项目中的子包构建完之后,再执行@freud/http 中的webpack构建命令,将rollup的构建产物lib/index.js 用webpack再构建一次。这样能够避免在子项目中再写一遍babel配置,做到所有子包的基础构建配置相同。

Guess you like

Origin juejin.im/post/7040821404782034980