跳转到内容

全自动分包

开发者不再需要关心小程序的单包 2M 限制。

应用代码可按照标准 Web 规则互相引用。

在实际产物中,主包引用分包,分包引用主包,分包引用分包,循环依赖引用,全部都没有问题。

只需决定“何时加载某功能”,而不必思考“这个功能该放哪个包”。

源码视角

一次动态导入

异步边界后续静态依赖 3.6M
构建产物

依赖自动拆包

主包与分包、分包与分包,均可互相调用

需要随 App 或页面一起启动的代码照常使用静态 import

import { initializeStore } from './store'
initializeStore()

从 App、页面及其依赖通过静态导入可达的模块会保留在主包。

在功能入口使用 import()

async function openReport() {
const { createReport } = await import('./features/report')
return await createReport()
}

只需要在功能入口使用一次动态 import()。这表明该模块可以被异步加载(和 Web 规则一致)。

该功能内部继续使用普通静态引用:

features/report.ts
import { collectData } from './collect-data'
import { renderPdf } from './render-pdf'
export function createReport() {
return renderPdf(collectData())
}

动态 import() 后面的静态依赖也会参与全自动拆包不需要把每个文件都改成动态导入。

即使 静态依赖超过 2M 大小限制也没关系

实际上,vpt 会分析所有依赖的引用关系,重写并解耦它们,把它们放置在合适的位置。

import { lazy, Suspense } from 'react'
import { View } from 'virtual:taro/components'
const Report = lazy(() => import('./features/report.tsx'))
function ReportEntry() {
return (
<Suspense fallback={<View>正在加载报表…</View>}>
<Report />
</Suspense>
)
}

./features/report.tsx 默认导出 React 组件。首次渲染 <Report /> 时会触发动态导入。

页面就是一个普通组件。

和 Web 一样,做个骨架屏,然后通过 React.lazy()<Suspense> 去动态加载真正的页面组件。这个组件就会被自动分包。

当然,页面内容也可以使用原生组件;按照原生组件设置后,可以通过同样的 <Suspense> 按需加载。

适合按需加载的通常是大型编辑器、图表、报表、导出工具或其他低频功能。应在完整功能的入口使用 import(),而不是逐个动态导入小型工具模块。

功能内部保持静态导入,只有确实需要更晚加载的部分才继续使用下一层 import()

全自动位置规划:指最终可能在主包,也可能在分包。当然,应用代码不需要关心这些分包信息。

源码关系结果
App、页面及其静态依赖小程序要求同步启动,所以保留在主包
仅通过动态 import() 到达的功能入口参与全自动位置规划
动态 import() 后面的静态依赖参与全自动位置规划;若同时也是启动依赖,则留在主包
按需功能内部的下一层动态 import()参与全自动位置规划
import type构建时移除,不影响位置规划

小程序原生组件会参与位置规划。vpt 会把原生组件目录的文件体积计入声明模块,并将目录输出到该模块最终所属的主包或分包。接入方式、类型 schema 和动态加载示例参见原生组件。 只要整个原生组件的目录不超过 2M,可以完全交给 vpt 自动规划。

固定 App 样式入口、它导入的全局样式、图片、字体和其他普通构建资源暂不参与位置规划;对这些资源的自动规划已列入后续版本。

位置规划算法、跨分包加载方式和小程序运行时原理参见模块系统