背景
近期笔者在使用Taro进行微信小程序开发,当引入Echarts图表库时,微信检测单包超限2M的一系列优化措施的踩坑记录,期望能指导读者少走一些弯路。
为什么选择Echarts?
因为已有项目使用了ec-echarts, ec-canvas使用了echarts.js, 所以暂时只能沿用, 由于echarts比较大, 建议新开发的简单功能可以使用别的画图组件,
单包超过2M,为什么?
不处理的情况下, 导致Taro认为echarts.js被多个模块所依赖,echarts.js会被打进common.js文件里, 被所有文件引用, echarts大约占用700k, 如果原有逻辑很多, 加上这700k就会超过单包2M限制, 导致上传报错
解决思路
- 拆分echarts到分包中
- 压缩其他的功能体积, 比如图片使用cdn等等
如何拆分echarts到分包
为了解决此问题,采用splitChunks打包配置,将echarts单独模块打包,然后在对应的依赖页面(addChunkPages)注入依赖,config/index.js的配置如下:
const DeviceEchartsChunkName = 'pages/device/echarts';
// 省略含多代码***
// 配置
{
mini: {
compile: {
exclude: [
// 跳过编译
path.resolve(__dirname, '..', 'src/pages/device/components/EcCanvas/echarts.js')
]
},
webpackChain(chain) {
chain.optimization.sideEffects(false)
chain.merge({
optimization: {
splitChunks: {
cacheGroups: {
[DeviceEchartsChunkName]: {
name: DeviceEchartsChunkName,
priority: 50,
test(module) {
return /pages[\\/]device[\\/]components[\\/]EcCanvas[\\/]echarts.js/.test(
module.resource
);
},
},
},
},
},
});
},
addChunkPages(pages, pagesNames) {
pages.set("pages/device/ecg-swk/measure/index", [DeviceEchartsChunkName]);
}
}
}
由于echarts.js本身已经经过编译, 所以排除它被webpack再次编译
这样echarts就会被打入到分包里面
但是这样会出现一个如图的问题:
ec-canvas组件找不到echarts模块依赖…
经过一系列的分析,发现Taro对原生微信组件splitChunks分包打包的依赖注入有问题官方还没有修复此问题…
需要在Taro编译成功后,手动修改编译后的ec-canvas.js,注入echarts依赖,如下图:
手动加上即可解决
新的问题
总不能在每次编译后,手动修改编译后的文件吧,如果哪天发版本忘记手动修改,将导致线上问题,风险高。
因此需要写一个Taro打包hack插件,自动注入编译后的echarts依赖代码。
书写Taro编译插件很简单,请参考官方文档即可,插件代码如下:
/*
解决chunk包没有引用资源的问题
https://blog.csdn.net/forevercjl/article/details/109536031
* */
const fs = require('fs');
const path = require('path');
module.exports.default = module.exports = (ctx, options) => {
// console.log('options:', options)
ctx.onBuildStart(() => {
})
ctx.onBuildFinish(() => {
const optionsData = Array.isArray(options) ? options : [options];
for(let i in optionsData){
const unitData = optionsData[i];
const target = path.join(ctx.paths.outputPath, unitData.fileDistPath);
const data = fs.readFileSync(target, 'utf8');
fs.writeFileSync(target, `${unitData.prependContent};${data}`)
}
})
}
然后在config/index.js里面加入plugin的配置
{
plugins: [
[path.resolve(__dirname, '..', 'plugin/chunkCacheRequirePlugin'), [
{
fileDistPath: 'pages/device/components/EcCanvas/ec-canvas.js', // 目标文件
prependContent: 'require("../../echarts");' // 在文件最前面添加的代码
}
]]
]
}
这样每次编译完之后都会给目标文件前面主动加上require("../../echarts");
这段引用代码, 防止出错