ue3 uni-app 主包 2 MB 危机?1 个插件 10 分钟瘦身
是指在一个分包中引用另一个分包中的组件(不限主包与分包),这里的组件就是 vue 文件;貌似支持把页面文件也作为组件引入。是指在一个分包中引用另一个分包中的模块(不限主包与分包),这里的模块可以是 js/ts 模块(插件)。可以不用在意可能会因为这个问题导致的页面空白问题了,如果还存在问题,欢迎反馈🙏,以上面的分包为例,放在每个分包root对应目录下的静态文件会被打包到此分包内。行为,实现了无感
关于分包优化的说明
- 在对应平台的配置下添加
"optimization":{"subPackages":true}开启分包优化 - 目前只支持
mp-weixin、mp-qq、mp-baidu、mp-toutiao、mp-kuaishou的分包优化 - 分包优化具体逻辑:
- 静态文件:分包下支持 static 等静态资源拷贝,即分包目录内放置的静态资源不会被打包到主包中,也不可在主包中使用
- js文件:当某个 js 仅被一个分包引用时,该 js 会被打包到该分包内,否则仍打到主包(即被主包引用,或被超过 1 个分包引用)
- 自定义组件:若某个自定义组件仅被一个分包引用时,且未放入到分包内,编译时会输出提示信息
分包内静态文件示例
"subPackages": [{
"root": "pages/sub",
"pages": [{
"path": "index/index"
}]
}]
以上面的分包为例,放在每个分包root对应目录下的静态文件会被打包到此分包内。
🚨 一声叹息:Vue3 时代官方把「分包优化」砍了!
| 维度 | Vue2(webpack) | Vue3(vite) |
|---|---|---|
| 官方策略 | 内置 SplitChunks,自动拆包 | ⚠️ 直接移除拆包逻辑 |
| 结果 | 主包轻松 < 2 MB | 所有依赖一股脑进 common/vendor.js,瞬间爆表 |
| 平台红线 | 微信小程序主包 ≤ 2 MB | 上线即拒审 |
结论:不是 Vue3 不能分包,而是官方没做;不想被 2 MB 卡脖子,就必须装
@uni-ku/bundle-optimizer。
🎏 功能与支持
适用于 Uniapp - CLI 或 HBuilderX 创建的 Vue3 项目
1.分包优化
- 静态文件:分包下支持 static 等静态资源拷贝,即分包目录内放置的静态资源不会被打包到主包中,也不可在主包中使用
- js文件:当某个 js 仅被一个分包引用时,该 js 会被打包到该分包内,否则仍打到主包(即被主包引用,或被超过 1 个分包引用)
- 自定义组件:若某个自定义组件仅被一个分包引用时,且未放入到分包内,编译时会输出提示信息
2. 模块异步跨包调用
允许使用 import() 语法,异步引用模块。
注意,这不是指静态导入,详见此处。
v2.1.0 版本开始,插件实现了 无感屏蔽 非法的 import() 行为,同时会有 log 提示开发者迁移写法:
- 小程序端对 vue 组件文件的
import()是非法的 - app端的编译格式是iife,无法使用
import()语法,故均视为非法,将全量屏蔽
3. 组件异步跨包引用
在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
🚀 使用
0. 插件可配置参数
!以下各参数均为可选参数,默认开启所有插件功能,并在项目根目录下生成
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 |
1. 引入 @uni-ku/bundle-optimizer
- 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
}),
],
})
2. 修改 manifest.json
需要修改 manifest.json 中的 mp-weixin.optimization.subPackages 配置项为 true,开启方法与vue2版本的uniapp一致。
{
"mp-weixin": {
"optimization": {
"subPackages": true
}
}
}
使用了
@uni-helper/vite-plugin-uni-manifest的项目,修改manifest.config.ts的对应配置项即可。
✨ 例子
以下例子均以CLI创建项目为例, HBuilderX 项目与以上设置同理。
现在已经支持 hbx 创建的 vue3 + vite、不以 src 为主要代码目录的项目。
分包优化
分包优化 是本插件运行时默认开启的功能,无需额外配置,只需要确认 manifest.json 中的 mp-weixin.optimization.subPackages 配置项为 true 即可。
模块异步跨包调用
模块异步跨包调用 是指在一个分包中引用另一个分包中的模块(不限主包与分包),这里的模块可以是 js/ts 模块(插件)。
TODO: 是否支持 json 文件?
TODO: 是否支持 vue 文件?当然,小程序环境引入 vue 文件一般是没有什么意义的。
目前实测,小程序环境下,千万不要对一个 vue 组件进行
import()这会导致这个 vue 组件对应的页面或者文件空白,和 “分包优化” 功能有些许冲突”,后续会尽可能填补这个缺陷随着新版本的到来
v2.1.0,对非法的import()行为,实现了无感的屏蔽操作,同时会有 log 提示开发者迁移写法可以不用在意可能会因为这个问题导致的页面空白问题了,如果还存在问题,欢迎反馈🙏,详见此处
可以直接使用 esm 的原生异步导入语法 import() 来实现模块的异步引入。
- h5:原生支持
- mp:转译成
require.async() - app:app端的编译格式是
iife,无法使用import()语法,本插件将全量屏蔽import()行为 - 其他 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)
})
组件异步跨包引用
组件异步跨包引用 是指在一个分包中引用另一个分包中的组件(不限主包与分包),这里的组件就是 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>
更多推荐
所有评论(0)