Tip
uni-app 分包优化插件化实现
前往 dcloudio/uni-app#5025 查看本项目立项背景。
前往 https://github.com/Vanisper/uniapp-bundle-optimizer 查看本插件详细发展过程与提交记录。
Caution
v2.0.0版本开始,有重大更新,如果您是从旧版本升级,请务必阅读 迁移指南 (MIGRATION.MD)。
!暂时没有对App平台做兼容性实现
适用于 Uniapp - CLI 或 HBuilderX 创建的 Vue3 项目
- 分包优化
- 模块异步跨包调用
允许使用
import()语法,异步引用模块。注意,这不是指静态导入,详见此处。
- 组件异步跨包引用
在vue 组件的
defineOptions宏指令或者默认导出下配置componentPlaceholder,eg:<!-- setup 模式(组合式) --> <script setup> import SubComponent from '@/pages-sub-async/component.vue' import SubDemo from '@/pages-sub-demo/index.vue' defineOptions({ componentPlaceholder: { SubComponent: 'view', SubDemo: 'view', }, }) </script>
<!-- 默认导出模式(选项式) --> <script> import SubComponent from '@/pages-sub-async/component.vue' import SubDemo from '@/pages-sub-demo/index.vue' // 同样支持支持 defineComponent export default { components: { SubComponent, SubDemo, }, componentPlaceholder: { SubComponent: 'view', SubDemo: 'view', }, } </script>
异步组件、异步模块引用基本原理:详见 https://developers.weixin.qq.com/miniprogram/dev/framework/subpackages/async.html
pnpm add -D @uni-ku/bundle-optimizer!以下各参数均为可选参数,默认开启所有插件功能,并在项目根目录下生成
async-component.d.ts文件
| 参数-[enable] | 类型 | 默认值 | 描述 |
|---|---|---|---|
| enable | boolean|object |
true |
插件功能总开关,object时可详细配置各插件启闭状态,详见下列 |
| enable.optimization | boolean |
true |
分包优化启闭状态 |
| enable['async-import'] | boolean |
true |
模块异步跨包调用启闭状态 |
| enable['async-component'] | boolean |
true |
组件异步跨包引用启闭状态 |
| 参数-[logger] | 类型 | 默认值 | 描述 |
|---|---|---|---|
| logger | boolean|string[] |
false |
插件日志输出总配置,true时启用所有子插件的日志功能;string[]时可具体启用部分插件的日志,可以是optimization、async-component、async-import |
- CLI:
直接编写根目录下的 vite.config.* - HBuilderX: 需要根据你所使用语言, 在根目录下
创建vite.config.*
// vite.config.*
import Uni from '@dcloudio/vite-plugin-uni'
import Optimization from '@uni-ku/bundle-optimizer'
import { defineConfig } from 'vite'
export default defineConfig({
plugins: [
Uni(),
Optimization({
enable: true,
dts: true,
logger: false,
}),
// 以上配置都是默认配置,可以直接不传任何配置
// Optimization(),
],
})// vite.config.*
import Uni from '@dcloudio/vite-plugin-uni'
import Optimization from '@uni-ku/bundle-optimizer'
import { defineConfig } from 'vite'
export default defineConfig({
plugins: [
Uni(),
// 可以无需传递任何参数,默认开启所有插件功能,并在项目根目录生成类型定义文件
Optimization({
// 插件功能开关,默认为true,即开启所有功能
enable: {
'optimization': true,
'async-import': true,
'async-component': true,
},
// 也可以传递具体的子插件的字符串列表,如 ['optimization', 'async-import', 'async-component'],开启部分插件的log功能
logger: true, // 默认 false
}),
],
})需要修改 manifest.json 中的 mp-weixin.optimization.subPackages 配置项为 true,开启方法与vue2版本的uniapp一致。
{
"mp-weixin": {
"optimization": {
"subPackages": true
}
}
}使用了
@uni-helper/vite-plugin-uni-manifest的项目,修改manifest.config.ts的对应配置项即可。
本项目为异步组件配置 componentPlaceholder 时,提供了 ts 类型标注,类型文件为 @uni-ku/bundle-optimizer/client。
可按需引用,下面分别提供 三斜线指令 与 tsconfig 两种配置方法。
在项目的入口文件(如 main.ts)顶部添加:
/// <reference types="@uni-ku/bundle-optimizer/client" />但是一般不会在入口文件写这个类型引用,而是有专门的
*.d.ts文件,内容同上。
在业务项目的 tsconfig 配置文件的 compilerOptions.types 数组中添加:
{
"compilerOptions": {
"types": [
"@uni-ku/bundle-optimizer/client"
]
}
}以下例子均以CLI创建项目为例, HBuilderX 项目与以上设置同理。
现在已经支持 hbx 创建的 vue3 + vite、不以 src 为主要代码目录的项目。
1. (点击展开) 分包优化
分包优化 是本插件运行时默认开启的功能,无需额外配置,只需要确认 manifest.json 中的 mp-weixin.optimization.subPackages 配置项为 true 即可。
详情见本文档中的 使用 部分。
2. (点击展开) 模块异步跨包调用
模块异步跨包调用是指在一个分包中引用另一个分包中的模块(不限主包与分包),这里的模块可以是 js/ts 模块(插件)。TODO:是否支持 json 文件?TODO:是否支持 vue 文件?当然,小程序环境引入 vue 文件一般是没有什么意义的。目前实测,小程序环境下,千万不要对一个 vue 组件进行
import()这会导致这个 vue 组件对应的页面或者文件空白,和 “分包优化” 功能有些许冲突”,后续会尽可能填补这个缺陷
可以直接使用 esm 的原生异步导入语法 import() 来实现模块的异步引入。
- h5:原生支持
- mp:转译成
require.async() - app:TODO: 待兼容
- 其他 mp:TODO: 未做兼容测试,欢迎反馈
// js/ts 模块(插件) 异步引入
await import('@/pages-sub-async/async-plugin/index').then((res) => {
console.log(res?.AsyncPlugin()) // 该插件导出了一个具名函数
})
// vue 文件 异步引入(页面文件)❌ 暂时不要这样使用,不要这样引用组件文件
import('@/pages-sub-async/index.vue').then((res) => {
console.log(res.default || res)
})
// vue 文件 异步引入(组件文件)❌ 暂时不要这样使用,不要这样引用组件文件
import('@/pages-sub-async/async-component/index.vue').then((res) => {
console.log(res.default || res)
})3. (点击展开) 组件异步跨包引用
组件异步跨包引用是指在一个分包中引用另一个分包中的组件(不限主包与分包),这里的组件就是 vue 文件;貌似支持把页面文件也作为组件引入。- 需要在 vue 组件的
defineOptions宏指令或者默认导出下配置componentPlaceholder。 - 由于小程序端需要
kebab-case风格的组件名称,插件内部会自动处理你的componentPlaceholder配置:将组件名称(key)以及占位目标组件名(value)转换成kebab-case风格。
setup 模式(组合式):
<!-- setup 模式(组合式) -->
<script setup>
import SubComponent from '@/pages-sub-async/component.vue'
import SubDemo from '@/pages-sub-demo/index.vue'
defineOptions({
componentPlaceholder: {
SubComponent: 'view',
SubDemo: 'view',
},
})
</script>默认导出模式(选项式):
可能有些环境不能使用 defineOptions 宏
<!-- 默认导出模式(选项式) -->
<script>
import SubComponent from '@/pages-sub-async/component.vue'
import SubDemo from '@/pages-sub-demo/index.vue'
// 同样支持支持 defineComponent
export default {
components: {
SubComponent,
SubDemo,
},
componentPlaceholder: {
SubComponent: 'view',
SubDemo: 'view',
},
}
</script>- 感谢 chouchouji 提供的配置式异步组件导入的思路,插件指路 👉 vite-plugin-component-placeholder。
详见讨论 #26 (comment)
- 感谢 vue-macros 项目提供的 vue-sfc 以及宏指令解析实现。
| 项目 | 描述 |
|---|---|
| Uni Ku | 有很多 Uniapp(Uni) 的酷(Ku) 😎 |
| create-uni | 🛠️ 快速创建uni-app项目 |
| Wot Design Uni | 一个基于Vue3+TS开发的uni-app组件库,提供70+高质量组件 |
加我微信私聊,方便定位、解决问题。
微信 |
如果我的工作帮助到了您,可以请我吃辣条,使我能量满满 ⚡
请留下您的Github用户名,感谢 ❤
微信 |
支付宝 |
Happy coding!


