前言
最近在接到一个二开项目,发现一个普通的小项目居然主包超过了1.5MB,并且甲方还在持续加码功能,一看就是一个屎山项目。为了更好的进行开发,我打算重新规划一下整个小程序,并且进行分包,而当我打算在清理一堆屎的时候我才发现,这堆屎有毒!原项目经过多个作者反复拉屎,完美的实现了主包拉屎,分包也拉屎的操作,导致整体已经很难优化了,因此我就想到是否可以使用异步组件和跨包加载js,从而剥离一部分的文件出来,实现主包体积优化。
上姿势点
在这里,我们需要先引入来自微信小程序官方的文档:分包异步化
微信小程序在2.11.2之后就已经支持分包异步化了,因此引入了俩个特性,支持 跨分包自定义组件引用 与 跨分包 JS 代码引用,应用这俩个特性我们可以去优化主包体积。
1. 跨分包自定义组件引用
跨分包自定义组件引用,需要搭配占位组件的配置才可以实现,根据微信小程序官方文档描述如下。
而在uniapp中,对应的我们需要在pages.json中进行如下配置
配置之后,我们就可以在页面中正常使用了,对应的slots、props、events的传递在分包加载进来之后便可以正常响应。
但是这一切看似美好,实际上还是存在部分问题的,主要如下
- (1) 在分包未加载完成之前,该组件为占位组件,如果是view,text等基础组件,则slots的内容会直接显示出来,影响用户体验
- (2) 该方案只支持直接在页面使用分包组件,页面内的子组件引入均无效
- (3) 该方案在遇到分包比较大的时候容易造成过长的加载时间等待
虽然存在着部分问题,但是我们依然可以将部分业务组件分离到分包中,然后使用跨包组件,从而减少主包的体积,在我这个项目中我对接的腾讯云IM就是通过这种形式,将消息列表对接到tabbar中,否则按照以往的经验这一部分肯定占据主包大量的空间。
2. 跨分包js调用
跨分包js调用,需要到require,而对于uniapp而言,直接使用require会导致报错,无法通过编译。因此我开发了一个插件,可以简单直接的实现调用分包js。
对应的插件地址:zion-uniapp-mp-load-package
对应的github demo地址: zionLZH/zion-uniapp-mp-load-package
const { zionUniMpLoadPackagePlugin } = require('zionUniMpLoadPackagePlugin/webpack')
module.exports = {
configureWebpack: {
plugins: [
new zionUniMpLoadPackagePlugin()
],
optimization: {
moduleIds: 'named',
}
},
}
这是vue3的,新增/修改vite.config.js
import { defineConfig } from 'vite';
import uni from '@dcloudio/vite-plugin-uni';
import { zionUniMpLoadPackagePlugin } from './script/zionUniMpLoadPackagePlugin/vite'
export default defineConfig({
plugins: [
uni(),
zionUniMpLoadPackagePlugin()
],
});
// 这里的packageA对应的就是分包目录
loadMpPackage("packageA", () => {
// ...
console.log('加载成功')
// 这里就可以直接引入分包中对应位置的js,调用其方法
console.log(loadMpPackageModule('/packageA/sdk/index.js'))
console.log(loadMpPackageModule('/packageA/sdk/index.js').a())
}, ({mod, errMsg}) => {
// ...
console.log('加载出错', mod, errMsg)
})
在使用我的插件之后,基本上很多第三方的js,或者比较占体积的js可以直接转移到一个独立的分包中,从而极大的减少主包的占用,我通过这个方式把高德,省市区,im,音视频等插件都进行了转移,终于把主包减少到了1M左右。
对了,如果有大佬不吝啬的话,也可以帮我点个star哦:https://github.com/zionLZH/zion-uniapp-mp-load-package
2024年7月26日:已经确定有的bug,仅存在vue2版本,引入插件之后导致主包体积反而增大,这仅在vue2/webpack版本存在,原因是因为webpack打包模块的时候moduleId被插件接管之后计算出来的moduleId有问题(因为分包里面需要进行重定向,导致分包的Id有问题,目前暂时没有一个完美的结局方案)。建议开发者自行根据项目实际跑起来的情况确定是否采用本方案(可以先引入插件,空跑一下看看前后主包体积),感谢评论区大佬提出与配合调试。