# 小程序分包 某些情况下,开发者需要将小程序划分成不同的子包,在构建时打包成不同的分包,用户在使用时按需进行加载。 在构建小程序分包项目时,构建会输出一个或多个分包。每个使用分包小程序必定含有一个主包。所谓的主包,即放置默认启动页面/*TabBar* 页面,以及一些所有分包都需用到公共资源/*JS* 脚本;而分包则是根据开发者的配置进行划分。 在小程序启动时,默认会下载主包并启动主包内页面,当用户进入分包内某个页面时,客户端会把对应分包下载下来,下载完成后再进行展示。 目前小程序分包大小有以下限制: - 整个小程序所有分包大小不超过 *20M* - 单个分包/主包大小不能超过 *2M* 对小程序进行分包,可以优化小程序首次启动的下载时间,以及在多团队共同开发时可以更好的解耦协作。 官方所提供的文档分为如下 *3* 个内容: - 使用分包 - 独立分包 - 分包预加载 所以这里不再照搬官网做介绍,详细了可以参阅官方文档:*https://developers.weixin.qq.com/miniprogram/dev/framework/subpackages.html* 本文我们主要来看一下分包的实际操作。 这里以【*applet-subcontracting*】项目为例。 根据官网的介绍,分包主要是将小程序的页面进行分门别类,例如: ```js ├── app.js ├── app.json ├── app.wxss ├── packageA │ └── pages │ ├── cat │ └── dog ├── packageB │ └── pages │ ├── apple │ └── banana ├── pages │ ├── index │ └── logs └── utils ``` 然后在 *app.json* 文件中使用 *subpackages* 字段来声明项目分包结构: ```js { "pages":[ "pages/index", "pages/logs" ], "subpackages": [ { "root": "packageA", "pages": [ "pages/cat", "pages/dog" ] }, { "root": "packageB", "name": "pack2", "pages": [ "pages/apple", "pages/banana" ] } ] } ``` *subpackages* 字段对应的值为一个数组,数组里面记录了分几个包,每个包对应一个对象,对象可以设置如下的属性值。如下: ![image-20230214085459929](https://xiejie-typora.oss-cn-chengdu.aliyuncs.com/2023-02-14-005500.png) 来看【*applet-subcontracting*】项目实际的操作示例。 image-20230214085516276 首先是我们的项目目录,以前我们所有的页面,都是放在 *pages* 目录下面的。现在要进行分包的话,虽然也都是放在 *pages* 目录下,但是 *pages* 目录下面又分为了 *package1、package2* 和 *package3*。 这里我们其实就是分成了 *3* 个包,每个包有自己的目录,展开后如下图所示: image-20230214085544467 接下来我们就需要在 *app.json* 里面进行配置了。配置代码片段如下: ```js { "pages":[ "pages/package1/pages/index/index", "pages/package1/pages/cat/cat", "pages/package1/pages/dog/dog", "pages/package1/pages/apple/apple", "pages/package1/pages/banana/banana" ], "subpackages": [ { "root": "pages/package2", "name": "pack2", "pages": [ "pages/cat/cat", "pages/dog/dog" ] }, { "root": "pages/package3", "name": "pack3", "pages": [ "pages/apple/apple", "pages/banana/banana" ] } ], // ... } ``` 可以看到,*pages* 里面配置第一次要加载的页面,这里我们加载的是 *package1* 里面的所有页面。 而 *package2* 和 *package3* 则采取的是分包的形式,被写入到了 *subpackages* 里面。 在开发工具的详情中,可以看到当前的分包情况,如下图所示: image-20230214085619380 ### 独立分包 独立分包就是这个包是独立的,不依赖于主包就能用,当设置为独立分包时,我们从独立分包进入不会加载主包,只有进入主包页面或者非独立分包页面是才加载主包。 使用的方法也很简单,只需要在配置包的时候,把 *independent* 设置为 *true* 就会成为独立分包。 例如: ```js { // ... "subpackages": [{ "root": "pages/package2", "name": "pack2", "pages": [ "pages/cat/cat", "pages/dog/dog" ], "independent": true }, { "root": "pages/package3", "name": "pack3", "pages": [ "pages/apple/apple", "pages/banana/banana" ] }], // ... } ``` 在上面的代码中,我们将 *pack2* 设置为了独立分包。 独立分包注意事项: - 从独立分包进入的时候,由于没有加载主包,因此通过 *getApp* 方法拿到的是 *undefined*。只有在加载主包回来这个页面以后才能通过 *getApp* 拿到全局参数。 - 独立分包不能共享其他包样式,包括 *app.wxss* 样式。 - 独立分包不支持使用插件 - 在低于 *6.7.2* 的微信版本的小程序独立分包当成普通分包对待,不具备独立分包的能力。 为了兼容独立分包进入无法全局管理变量的能力,官方在基础版本库 *2.4.4* 以后做了兼容,使用 *getApp({allowDefault: true})* 可以预先写入变量,当主包加载的时候会同步到 *app* 里面。 ```js const app = getApp({allowDefault: true}); app.aa = 1; // 等主包加载的时候会同步进去 ``` ### 分包预加载 所谓分包预加载,就是在进入小程序某个页面时,由框架自动预下载可能需要的分包,提升进入后续分包页面时的启动速度。 例如: ```js { // ... "preloadRule": { "pages/package1/pages/cat/cat": { "network": "all", "packages": ["pack2"] }, "pages/package1/pages/apple/apple": { "network": "all", "packages": ["pack3"] } }, // ... } ``` 在上面的配置中,表明进入 *cat* 页面时,就加载 *pack2* 这个包,进入 *apple* 这个页面时,就加载 *pack3* 这个包。 而 *network* 对应的 *all* 代表在指定网络下预下载,可选值有 *all*(不限网络)和 *wifi*(仅 *wifi* 下预下载)。 ## 分包异步化 在小程序中,不同的分包**对应不同的下载单元**。 不同的包之间无法相互使用自定义组件或者 require。 ```js subpackA item 自定义组件 subpackB ``` **跨分包自定义组件引用(占位渲染)** 有点类似于骨架屏,先用内置组件或者本包中的组件进行一个占位渲染,之后在其他包加载之后再渲染为对应的组件。 要使用此特性,直接在当前包对应的 json 文件中进行配置即可: ```js { "componentPlaceholder": { "button": "view", "list": "simple-list" } } ``` **跨分包 JS 代码引用** 在当前包如果要使用其他包的代码,首先通过 require 来引入,然后注意这个过程是异步的。 -*EOF*-