小程序uni-app(vue3)主包体积优化方案(SDK过大问题)
以腾讯im和lottie库为例,分享了两种因为sdk,导致主包超过2mb无法发布的问题。方案一:业务代码和SDK都在分包、方案二:业务代码在主包,SDK在分包
·
方案一:业务代码和SDK都在分包
- 基于
@rollup/plugin-commonjs - 不同的业务代码可以分包
案例(lottie):
- 将lottie的业务代码和lottie库、lottie动画文件放到根目录的lottie文件夹下(
node_modules的源文件建议删除) - 开启分包模式(manifest.json),在page.json文件中注册lottie分包,和预加载该分包
- 安装依赖
pnpm install @rollup/plugin-commonjs -d - 创建vite.config.js文件
import { defineConfig } from 'vite';
import uni from '@dcloudio/vite-plugin-uni';
import commonjs from "@rollup/plugin-commonjs";
export default defineConfig({
plugins: [uni(),commonjs()]// 使rollup可以打包cjs规范的npm代码
});
- 在lottie的业务代码中引用自己的lottie库和lottie动画文件即可
方案二:业务代码在主包,SDK在分包
- 基于分包异步化、
@rollup/plugin-commonjs - 业务代码不能从主包拆分
案例(lottie):
- 将lottie库、lottie动画文件放到根目录的lottieSDK文件夹下(
node_modules的源文件建议删除) - lottieSDK分包目录下创建入口页面(用户欺骗uni-app以为你是用了lottie相关依赖)
- 开启分包模式(manifest.json),在page.json文件中注册lottieSDK分包和入口页面,和预加载该分包
- 安装依赖
pnpm install @rollup/plugin-commonjs -d - 创建vite.config.js文件
import { defineConfig } from 'vite';
import uni from '@dcloudio/vite-plugin-uni';
import commonjs from "@rollup/plugin-commonjs";
export default defineConfig({
plugins: [uni(),commonjs()]// 使rollup可以打包cjs规范的npm代码
});
- lottieSDK分包入口文件
index.vue引用所有用到的依赖
<script>
// 这个地方需要引用一下这个包里所有需要打包的sdk 欺骗uni-app以为你使用了分包里的sdk
import lottie from './lottie/index.js';
import animationData from './static/lottie.js';
let ani = null; // 必须放在外面,uni里不要挂在this上,否则会触发循环引用的报错
export default {
data() {},
methods: {
init() {
this.createSelectorQuery()
.select('#lottie_demo')
.node(res => {
console.log(res); // 节点对应的 Canvas 实例。
const canvas = res.node;
const context = canvas.getContext('2d');
canvas.width = 300;
canvas.height = 300;
lottie.setup(canvas);
ani = lottie.loadAnimation({
loop: true,
autoplay: true,
animationData: animationData,
rendererSettings: {
context
}
});
})
.exec();
}
}
};
</script>
- 在lottie的业务代码中引用lottieSDK中的依赖
<template>
<view class="container">
<view style="text-align: center;">
<canvas id="lottie_demo" type="2d" style="display: inline-block; width: 300px; height: 300px;" />
<button @tap="init" style="width: 300px;">初始化</button>
<button @tap="play" style="width: 300px;">播放</button>
<button @tap="pause" style="width: 300px;">暂停</button>
</view>
</view>
</template>
<script>
import { onShow } from '@dcloudio/uni-app'
let ani = null; // 必须放在外面,uni里不要挂在this上,否则会触发循环引用的报错
export default {
data() {
return {
lottie : null,
animationData : null,
inited: false
};
},
async onShow() {
await require
.async('../../lottieSDK/lottie/index.js')
.then(({
lottie
}) => {
this.lottie = lottie;
console.log('lottie',this.lottie);
})
.catch((res) => {
console.log(res);
});
await require
.async('../../lottieSDK/static/lottie.js')
.then((animationData) => {
this.animationData = animationData;
console.log('animationData',this.animationData);
})
.catch((res) => {
console.log(res);
});
},
methods: {
init() {
if (this.inited) {
return;
}
this.createSelectorQuery()
.select('#lottie_demo')
.node(res => {
console.log(res); // 节点对应的 Canvas 实例。
const canvas = res.node;
const context = canvas.getContext('2d');
canvas.width = 300;
canvas.height = 300;
this.lottie.setup(canvas);
ani = this.lottie.loadAnimation({
loop: true,
autoplay: true,
animationData: this.animationData,
rendererSettings: {
context
}
});
this.inited = true;
})
.exec();
},
play() {
ani.play();
},
pause() {
ani.pause();
}
}
};
</script>
master分支是无优化方案businessPackage分支是方案一:业务代码和SDK都在分包
主包196KB、lottie分包492KB 压缩后:主包83KB、lottie分包403KBasyncPackage分支是方案二:业务代码在主包,SDK在分包
腾讯IM案例
业务代码与 IM SDK 打包到“IM”分包
- 将
TUIKit文件夹移动到im分包目录下,App.vue和login.vue中的代码移动到im分包的page目录下 - 将
node_modules目录下的im相关依赖移动(chat,chat-uikit-engine,tim-profanity-filter-plugin,tim-upload-plugin,tui-core)到im分包的@package目录下
使所有的im代码和功能都放在im分包下
-
开启分包模式(
manifest.json),im分包路由(pages.json) -
安装依赖
npm install @rollup/plugin-commonjs path -d -
创建vite.config.js文件
import {
defineConfig
} from 'vite';
import uni from '@dcloudio/vite-plugin-uni';
import commonjs from "@rollup/plugin-commonjs";
import path from "path";
export default defineConfig({
plugins: [uni(),
commonjs() // 使rollup可以打包cjs规范的npm代码
],
resolve: {
alias: { // im的依赖之间有互相的引用, 通过别名将彼此关联起来(因为别名和原名一致,node_modules的依赖需要删掉)
"@tencentcloud": path.resolve(__dirname, "im/@onmcPackage/"),
"tim-upload-plugin": path.resolve(__dirname, "im/@onmcPackage/tim-upload-plugin"),
"tim-profanity-filter-plugin": path.resolve(__dirname,"im/@onmcPackage/tim-profanity-filter-plugin")
}
}
});
IM 业务代码在主包, IM SDK 在“ IM SDK”分包中
敬请期待
更多推荐



所有评论(0)