一 背景

分包是小程序给出的类似于web异步引入的一个方案,把一些初始进入时不需要的页面放到分包里,跳转到对应页面时再去下载分包,从而有效减少主包体积。
项目背景:
公司的小程序项目使用taro来实现一码多端,公共库和基础库放在了主包,导致主包体积体积超出了2M,无法本地预览。本次就是记录一下包体积优化的分析过程和解决思路。

1.目前小程序分包有以下限制:

  • 整个小程序所有分包大小不超过20M
  • 单个分包/主包大小不超过2M

2.什么是主包和分包

小程序在app.json的subpackages字段声明分包结构:
原本的项目路径:

├── app.js
├── app.json
├── app.wxss
├── packageA
│   └── pages
│       ├── cat
│       └── dog
├── packageB
│   └── pages
│       ├── apple
│       └── banana
├── pages
│   ├── index
│   └── logs
└── utils

分包:

{"pages":["pages/index","pages/logs"],"subpackages": [{"root": "packageA","pages": ["pages/cat","pages/dog"]}, {"root": "packageB","name": "pack2","pages": ["pages/apple","pages/banana"]}]
}

说明:

字段 类型 说明
root String 分包根目录
name String 分包别名,分包预下载时可以使用
pages StringArray 分包页面路径,相对于分包根目录
independent Boolean 分包是否是独立分包

使用分包后的打包原则:

  • 声明subpackages后,将按subpackages配置路径进行打包,subpackages配置路径外的目录将被打包到主包中
  • subpackage的根目录不能是另外一个subpackage内的子目录
  • tabBar页面必须在主包内

也就是说,主包用来放启动页/tabBar页面,以及公共资源和js脚本,而分包则根据开发者的配置进行划分。在小程序启动时,默认会下载主包并启动主包内页面,当用户进入分包内某个页面时,客户端会把对应分包下载下来,下载完成后再进行展示。

二 主包的依赖分析

项目打包后,在开发者工具->详情->基本信息->本地代码->代码依赖分析,点击后即可看到主包和各个分包的体积大小。

可以看到主包的体积已经超过2M了,这就必须要对包体积进行优化,否则无法本地预览和发布。
但是我们光看到vendors.js文件体积大是不管用的,我们得知道到底是vendors.js下面的哪些文件占用的体积多,从而才能更好的优化。这就需要借助其他一些工具,如webpack-bundle-analyzer这样的一个webpack插件去做辅助分析,它可以直观的分析出打包的文件包含哪些,大小占比,模块包含关系,依赖项,文件是否重复,压缩后大小如何等等情况。

1.webpack-bundle-analyzer

(1)介绍
本项目的taro版本为3.1.4,taro使用webpack作为内部的打包系统。有时候我们在业务代码中使用了require语法或者import default语法,webpack并不能给我们提供tree-shaking的效果。这时我们需要webpack-bundle-analyzer插件,该插件会在浏览器打开一个可视化的图表页面告诉我们引用各个包的体积。

(2)配置

// 引入依赖
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;const config = {...mini: {webpackChain (chain, webpack) {chain.plugin('analyzer').use(BundleAnalyzerPlugin)}}
}

编译后我们就可以看到具体的包图了:

开始对上图进行分析:

  • vendors.js里node_modules占比最大,且taro-ui/dist在node_modules占比也很大。这部分需要仔细分析原因。
  • 同时@wallet/taro-cashier占比很大,考虑到这是公司其他团队提供的组件,已通知该团队对包体积进行优化。
  • 剩下的包中我们看到bn.js体积较大,且重复打包。

三 问题解决

关于哪些文件会打包到vendors.js中以及taro项目为什么会出现重复打包的问题
在开发小程序时,taro编译器依赖SplitChunksPlugin插件抽取公共组件,默认主包、分包依赖的公共库都会打包到根目录vendors.js文件中(有一个例外,当只有分包里面有且只有一个页面依赖公共库时,会打包到分包中依赖页面源码中),直接影响到小程序主包大小,很容易超出2M的限制大小。

只要被两个chunk引用的文件,就被打包到主包的common,而分包的每一个页面打包完后都是一个独立的chunk,那就是只要分包里有两个页面引用了同一个文件,这个文件就会被打包到common.js。

1.bn.js重复打包的问题

方法:配置路径别名

module.exports = {alias: {'bn.js': path.resolve(process.cwd(), 'node_modules', 'bn.js')},
}

重新打包,发现bn.js只打包了一次:

2.taro-ui/dist包太大

项目中只有少数几个文件用到了taro-ui的组件,在具体引用时是这样做的:

//引用单个ui组件
import { AtButton } from 'taro-ui'//全局引入样式(css中)
@import "~taro-ui/dist/style/index.scss";

但是在排查样式时发现全局引用了两次样式:

删除其中一个再次打包:

对比第一次的app.wxss减少了300多k。

而且在打包的时候,taro-ui已经被全部打包进去了,webpack并没有tree-shaking掉未引用的组件,也就是说,官方的按需引入实际上并无法实现。
看了相关的资料以及github上关于这个问题的解决方案:
taro-ui打包问题优化

github关于taro-ui按需引入的解决方案

先采用了最简单的方案,在alias添加:

alias: {'taro-ui$': 'taro-ui/lib/index',
},

这样就可以直接加载taro-ui/lib/index中相关的组件,未加载也会被优化掉。

这么做之后直接把taro-ui/dist给干掉了。但是实际上只对js进行按需引入的话是不够的,还想对样式进行按需引入,因为项目的app.wxss和common.wxss体积还是很大,因此考虑第二个方案。

第二个方案,也就是链接一中的方案。

cnpm i babel-plugin-import --save-dev

在babel.config.js中进行如下配置:

const { includes } = require("lodash");
module.exports = {plugins: ['@babel/plugin-proposal-optional-chaining',["import", {libraryName: "taro-ui",customName: (name, file) => {const nameSection = name.split('-')if (nameSection.length === 4) {// 子组件的路径跟主组件一样nameSection.pop()}// 指定组件做路径映射const pathMap = {'tabs/pane': 'tabs-pane','modal-action': 'modal/action','modal-content': 'modal/content','modal-header': 'modal/header'}const path = nameSection.slice(1).join('-')return `taro-ui/lib/components/${pathMap[path] || path}`},style: (name) => {if (includes(name, '/modal')) {return 'taro-ui/dist/style/components/modal.scss'}const wholePath = name.split('/')const compName = wholePath[wholePath.length - 1]const fix = {'tabs-pane': 'tabs',// 2、或者在这里写映射,这里正好跟上面的映射相反// 'modal/action': 'modal',// 'modal/header': 'modal',// 'modal/content': 'modal',}[compName]return `taro-ui/dist/style/components/${fix || compName}.scss`}}]],presets: [['taro', {framework: 'react',ts: true,hot: false // 处理h5 babel运行报错 https://github.com/NervJS/taro/releases?after=v3.1.1}]]
}

删除全局引用的css样式:

// @import "~taro-ui/dist/style/index.scss";

重新打包:

可以看到app.wxss和common.wxss体积都很小了。
注意:
由于taro-ui的路径很不结构化,组件中的子组件可能又要额外的去引用,这样的话代码维护会比较麻烦,因此如果以后要在项目中新增之前没有的taro组件,一定要进行额外的配置。而且如果taro-ui版本升级,那就意味着我们可能需要根据官方的版本不断去优化配置,工作量极大且意义不大。

3.其他的解决方案

(1)使用optimizeMainPackage,terser-webpack-plugin和miniSplitChunksPlugin插件
这部分的优化方案在这里查看:https://taro-docs.jd.com/taro/docs/mini-split-chunks-plugin
具体的配置为:

const TerserPlugin = require("terser-webpack-plugin");
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
const MiniSplitChunksPlugin = require('mini-split-chunks-plugin')
const config = {mini: { optimizeMainPackage: {enable: true},webpackChain (chain, webpack) {process.env.TARO_ENV === 'weapp' && chain.plugin('optimizeMainPackage').use(MiniSplitChunksPlugin).before('miniPlugin')chain.plugin('analyzer').use(BundleAnalyzerPlugin);chain.merge({plugin: {terse: {plugin: TerserPlugin,args: [{minify: TerserPlugin.swcMinify,terserOptions: {compress: true,},}]}},})}},}
}

(2)替换一些体积较大的组件
如将moment.js换成day.js

以上就是小程序包体积优化的整个过程,本次已经将主包的2.54M减少到了1.76M。

小程序打包体积过大的解决方案相关推荐

  1. 解决uniapp小程序打包体积超过2M,提示包体积超过2M,“main packagexxx”,不给上传和预览的解决办法,绝对有效

    解决办法,原文地址: 解决uniapp小程序打包体积超过2M,提示包体积超过2M,"main packagexxx",不给上传和预览的解决办法,绝对有效!在微信小程序开发中,为了解 ...

  2. 微信小程序引入echarts过大最佳解决方案、echarts在微信开发者工具中不跟随滑动、使用echarts控制台提示使用canvas 2d

    一.微信小程序引入echarts过大最佳解决方案 微信上传时代码包大小限制为2MB,但是当我们引入echarts以后,单echarts代码包已经973KB,因此再结合额外的业务代码以及其他资源很有可能 ...

  3. 小程序打包体积优化策略

    背景 我们都知道微信小程序有包体积限制,整个小程序所有分包大小不超过 20M,单个分包/主包大小不能超过 2M.然而面对业务的不断更新迭代,代码和资源会越来越多,如果不尽早规划包体积的治理,势必有一天 ...

  4. 微信小程序包体积过大解决方法

    因为微信开发者工具提交需要整个项目大小不超过2M,超过2M则不能提交,会出现下面这个报错 解决方法: 1.在Hbuilder x上面勾选上运行时压缩代码 2.分包操作 在pages.json文件中设置 ...

  5. 小程序包体积压缩优化,下降500k起步

    由于公司小程序包体积过大,已经达到1.9m了,微信定义小程序单个代码包(主包/分包)上限为2m,所以小程序该减肥了 如果你按我的步骤都做了,体积没有减少,ok,来打我 文章目录 第一步:最直接的方式 ...

  6. 第六十二期:腾讯云发布“小程序·云开发十大优秀实践”:猫眼、唯品会等入选

    作者:周小白 [TechWeb]10 月 19 日消息,今日,腾讯云首次对外公布了"小程序·云开发十大优秀实践",包括白鹭引擎.千墨科技.腾讯新闻.即速应用.微盟.唯品会.猫眼.香 ...

  7. c语言做一个小程序报告,《C语言程序设计实践》课程报告30个小程序组合成一个大程序.doc...

    北方民族大学 课 程 报 告 课 程 名 称: 程序设计实践 专 业 班 级 : 软件工程(2)班 学 生 姓 名 : 李思良 学 号 : 任 课 教 师 : 王晓锋 学 期 : 2015-2016学 ...

  8. 腾讯云发布“小程序·云开发十大优秀实践”,猫眼、唯品会、香格里拉等入选

    10月19日,腾讯云联合微信小程序团队举办"小程序·云开发"技术峰会.会上,腾讯云首次对外公布了"小程序·云开发十大优秀实践", 包括白鹭引擎.千墨科技.腾讯新 ...

  9. 微信小程序Tab选项卡切换大集合

    代码地址如下: http://www.demodashi.com/demo/14028.html 一.前期准备工作 软件环境:微信开发者工具 官方下载地址:https://mp.weixin.qq.c ...

最新文章

  1. AC日记——信息传递 洛谷 P2661 (tarjan求环)
  2. textContent、innerHTML、innerText、outerText、outerHTML、nodeValue使用场景和区别
  3. rowid会变化么_升级后的饿了么,将成为阿里引领数字化的先锋
  4. 【论文解读】传统图像处理与深度学习又一结合:时空多尺度非局部自相似集成视频超分...
  5. java 2_Java(二)
  6. 02.改善深层神经网络:超参数调试、正则化以及优化 W2.优化算法(作业:优化方法)
  7. ER图和关系模型到MySQL数据库表
  8. 亮点抢先看,华为云 TechWave 大数据专题日有啥料?
  9. 几种 vue的数据交互形式
  10. 002-用python设计的第一个游戏
  11. 手机图片怎么免费转换成PDF格式?教程来了
  12. 计算机网络原理 思维导图
  13. 叉积 微分 恒等式_一个斜三角中的恒等式
  14. ipa java_Java 解析 IPA 文件,读取 Info.plist 信息
  15. ADS 修改绘图单位
  16. word文档另存为pdf格式,如何设置导航栏
  17. 用数据说话,看中国49个地方(省、市、高新区)集成电路产业实力情况
  18. 计算机总评等级怎么弄,excel总评等级怎么做?
  19. 互联网行测笔试题之最头疼的找规律
  20. ubuntu双系统时间同步_解决Windows与Ubuntu双系统时间同步问题

热门文章

  1. 对于LM法和信赖域的理解
  2. 如何制作一个简单的电子产品
  3. 初学uniapp上手项目
  4. Windows文件系统中文件的储存原理、文件粉碎机的原理、数据恢复的原理
  5. 让Windows XP系统启动时不输入密码自动登录
  6. 如何编写Linux 下的 USB 键盘驱动
  7. 基于Springboot外卖系统05:用户非登陆状态的页面拦截器实现
  8. ROS 2 ardent apalone安装和使用说明
  9. Struts2的结果集
  10. make menuconfig配置方法