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.js
also 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.js
will be ./lib/adapters/xhr.js
replaced 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.js
still referenced adapter/http
Figure 1 Figure 2
So far, we have roughly two directions to solve the problem:
- Build tool tweaks and optimizations
- Modify the source code to avoid redundant references
specific plan
So the corresponding solutions are:
- Upload axios to the private library and delete the relevant references to http.js
- Using the patch mechanism of the npm package,
@freud/http
modify the source code of axios in , and delete the relevant references to http.js - Split into
@freud/http
2 npm packages, corresponding to the web environment and the applet environment respectively - Use webpack instead
@freud/http
for packaging - 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配置,做到所有子包的基础构建配置相同。