@taro-minify-pack/plugin-async-pack
v0.1.4-alpha.2
Published
异步加载主包代码,优化主包体积(仅包含异步模块`js`文件)
Readme
@taro-minify-pack/plugin-async-pack
异步加载主包代码,优化主包体积(仅包含异步模块js文件)
✨ 功能特性
- 主包体积优化:将动态导入的模块自动拆分到异步分包,有效减少主包体积
- 灵活配置:可自定义异步分包名称前缀和数量
- 自动化处理:自动修改小程序配置文件,无需手动操作
- 性能提升:减少小程序启动时间,提升用户体验
📦 安装
npm install @taro-minify-pack/plugin-async-packyarn 安装
yarn add @taro-minify-pack/plugin-async-packpnpm 安装
pnpm add @taro-minify-pack/plugin-async-pack⚙️ 配置
babel配置
// babel-preset-taro 更多选项和默认值:
// https://docs.taro.zone/docs/next/babel-config
module.exports = {
presets: [
['taro', {
framework: 'react',
ts: true,
compiler: 'webpack5',
// 在原有基础上添加这个配置即可
'dynamic-import-node': process.env.TARO_ENV !== 'weapp',
}]
]
}Taro 配置
// config/index.js
module.exports = {
compiler: {
type: 'webpack5',
prebundle: {
// 关闭预打包,这里和分包异步编译有冲突
enable: false,
}
},
plugins: [
['@taro-minify-pack/plugin-async-pack', {
// 异步分包名前缀,默认为 'dynamic-package'
dynamicPackageNamePrefix: 'dynamic-package',
// 异步分包数量,默认为 1
dynamicPackageCount: 2,
// 自定义异步分包,最终输出目录格式为 `${dynamicPackageNamePrefix}-${name}`
customDynamicPackages: [
{
name: 'report',
test: (module) => /src[\\/]pages[\\/]report[\\/]/.test(module.resource || ''),
// 异步分包是否异步加载样式,默认为 false,设置为 true 后,该分包下的样式文件会被异步加载(由于异步加载样式存在延时时机不可控,建议仅用于非页面首屏组件)
asyncStyle: true
}
]
}],
],
};🚀 使用
基本使用
// 动态导入模块
const module = await import('./dynamic-module')React 组件懒加载
import { lazy, Suspense } from 'react'
const DynamicComponent = lazy(() => import('./DynamicComponent'))
function App() {
return (
<Suspense fallback={<div>Loading...</div>}>
<DynamicComponent />
</Suspense>
)
}Vue 组件懒加载
<template>
<view class="index">
<Suspense>
<template #default>
<AsyncComponent/>
</template>
<template #fallback>
<view>loading...</view>
</template>
</Suspense>
</view>
</template>
<script setup>
import {defineAsyncComponent, ref} from 'vue'
const AsyncComponent = defineAsyncComponent(() => import('./async-component')
)
</script>📝 工作原理
Webpack 配置修改:
- 覆盖
splitChunks规则,使common与vendors只处理同步模块 - 配置
chunkFilename生成规则,确保异步模块正确输出到指定分包 - 修改
miniCssExtractPlugin配置,确保异步模块的样式文件也能正确拆分到指定目录 - 修改
runtime.js输出,确保异步模块的js文件能通过require.async正确引入
- 覆盖
样式处理:
- 默认会先把未开启异步样式的分包样式合并成
${dynamicPackageNamePrefix}.wxss - 编译
app.wxss时自动补上一条@import './${dynamicPackageNamePrefix}.wxss',让这部分样式继续跟随主包同步加载 - 当
customDynamicPackages[].asyncStyle = true时,会在对应自定义分包下额外生成一个inject-style组件 - 这个组件会收集该分包目录下的所有
.wxss文件,并生成多个@import './xxx.wxss'引用,让样式跟随分包一起下发 - 构建结束后会继续改写
app.json和页面wxml:把inject-style注册到usingComponents/componentPlaceholder,再把组件节点追加到页面模板中,借此触发该分包样式的异步加载
- 默认会先把未开启异步样式的分包样式合并成
小程序配置修改:
- 自动修改
app.json,添加异步分包配置
- 自动修改
⚠️ 注意事项
- 仅支持微信小程序:当前插件仅适用于微信小程序环境
- 关闭预打包:必须关闭 Taro 的预打包功能,否则可能与异步分包功能冲突
- Babel 配置:需要正确配置 Babel 的
dynamic-import-node选项 - Webpack 版本:仅支持 Webpack 5 编译器
- 分包数量:根据项目实际情况配置
dynamicPackageCount,过多的分包可能会影响性能
🔧 配置选项
| 选项名 | 类型 | 默认值 | 描述 |
|----------------------------|--------------------------|--------------------|-----------|
| dynamicPackageNamePrefix | string | 'dynamic-package' | 异步分包名称前缀 |
| dynamicPackageCount | number | 1 | 异步分包数量 |
| customDynamicPackages | CustomDynamicPackage[] | [] | 自定义异步分包配置 |
customDynamicPackages 配置说明
interface CustomDynamicPackage {
name: string
test: string | RegExp | ((module, context) => boolean)
asyncStyle?: boolean
}name:自定义异步分包标识,最终会拼成${dynamicPackageNamePrefix}-${name},例如dynamic-package-reporttest:直接透传给 webpacksplitChunks.cacheGroups[packageName].test,命中的异步模块会被拆到该分包asyncStyle:默认false。开启后会为该分包额外生成inject-style组件,并自动注入到页面模板中,让该分包内样式跟随组件异步加载
customDynamicPackages 配置示例
plugins: [
['@taro-minify-pack/plugin-async-pack', {
dynamicPackageNamePrefix: 'dynamic-package',
dynamicPackageCount: 2,
customDynamicPackages: [
{
name: 'sync-style',
test: (module) => /src[\\/]pages[\\/]sync-style[\\/]/.test(module.identifier()),
},
{
name: 'async-style',
test: (module) => /src[\\/]pages[\\/]async-style[\\/]/.test(module.identifier()),
asyncStyle: true
}
]
}]
]上述配置会额外生成 dynamic-package-sync-style 和 dynamic-package-async-style 两个异步分包;其中 async-style 分包会同时产出 inject-style 组件,并在编译时自动追加到 app.json 与页面模板中。
🤝 常见问题
1. 异步模块没有被拆分到分包?
- 请检查是否正确配置了
dynamic-import-node选项 - 确保已关闭 Taro 的预打包功能
- 确认使用了 Webpack 5 编译器
- 确保代码中使用了
import()动态导入语法
2. 为什么样式文件没有异步?
- 先检查
customDynamicPackages[].test是否真的命中了目标模块;如果没有命中,样式会走默认同步合并逻辑,而不会进入对应自定义异步分包 - 再检查该自定义分包的
asyncStyle是否为true;只有开启后才会额外生成inject-style组件,并触发异步样式注入 module.identifier()代表 webpack 给当前模块生成的唯一标识,通常会包含 loader 链、查询参数和源文件绝对路径,比单纯看文件名更适合排查test是否命中- 排查时可以先在
test回调里临时打印module.identifier(),确认真实值后再收窄正则规则,例如只匹配其中稳定的源码路径片段:
const customDynamicPackageConfig = {
name: 'async-style',
test: (module) => {
console.log(module.identifier())
return /src[\\/]pages[\\/]async-style[\\/]/.test(module.identifier())
},
asyncStyle: true
}- 如果打印出来的内容带有
css-loader、sass-loader、?taro之类前缀或查询参数,通常是正常现象,优先匹配其中稳定的业务目录路径即可
3. 配置后编译失败?
- 请检查配置选项是否正确
- 确认 Taro 版本与插件版本兼容
- 查看编译日志,排查具体错误原因
4. 页面加载时出现白屏?
- 请检查是否正确使用了
Suspense组件包裹异步组件 - 确保异步组件的导入路径正确
- 检查网络请求是否正常
5. 分包数量配置后没有生效?
- 请确保
dynamicPackageCount配置的值大于0 - 检查是否有足够的动态导入模块来拆分到多个分包
📄 许可证
MIT License
🤝 贡献
欢迎提交 Issue 和 Pull Request!
该插件是 @taro-minify-pack 系列插件的一部分,致力于提供完整的 Taro 项目优化解决方案。
