返回博客

微信小程序分包不能嵌套分包——一个让编译器报 should not contain 的隐藏禁令

某个微信小程序的单包体积逼近 2MB 限制,想把其中一个大分包里的几个子目录拆出去,减轻这个包的体积压力。配置写好提交,微信开发者工具刷出一条让人摸不着头脑的报错,折腾半小时才搞清楚这是平台层的一条硬性禁令——而不是自己哪里写错了。

现象

app.jsonsubpackages 数组里,已存在一个分包:

{ "root": "packagePerson", "pages": [...] }

想把其中七个子目录拆成独立分包,于是新增:

{ "root": "packagePerson/pages/qixi", "pages": [...] }

保存后编译器立即报错:

app.json: ["subpackages"][22]["root"] should not contain ["subpackages"][15]["root"]

根因

微信小程序的分包加载规则有一条严格约束:subpackages 数组内,任意两个分包的 root 路径不允许存在前缀包含关系

换言之,packagePerson/pages/qixipackagePerson 为前缀,框架判定这是"分包嵌套分包",直接拒绝。

坑:主包可以有子目录分包,分包不行

很多人参照过这种写法:

{ "root": "pages/preview", "pages": [...] }

这是从主包的 pages/ 目录下拆出来的,之所以合法,是因为主包没有 root 字段,它由顶层 pages 数组定义,不参与 subpackages 前缀嵌套检测

一旦你把 packagePerson 也放入了 subpackages,再往 packagePerson/ 下挂任何子分包,就会触发这条禁令——哪怕物理目录结构完全正确。

正解

面对"大分包超体积想拆"的诉求,有三条可行路径,按代价从低到高排列:

方案一(最轻):注销已下线页面

如果该分包里有若干历史遗留页面不再需要,直接从 app.json 里删除注册(保留物理文件不动),体积立刻下降,不需要改任何跳转路径。

方案二(中等):新增独立顶级分包

把要拆出去的子目录整体移动到一个全新的顶级分包root 使用从未出现过的名字,例如 packageActivity

{ "root": "packageActivity", "pages": ["pages/qixi/index"] }

代价是需要 codemod 所有 navigateTo 路径,同时更新后端配置里硬编码的页面路径(如消息推送 bannerLink、活动跳转 URL 等)。

方案三(重型):解散原大分包

把原来的大分包完全解散,将每个子目录分别升级为顶级独立分包。好处是颗粒度最细,坏处是主包的共享资源(utils/components/miniprogram_npm/)会被各分包重复引用,反而可能撑大总包体积。

正解:拆分包必须用全新顶级 root,不能在已有分包目录下挂子路径

目标目录结构不影响 app.json 配置写法。物理上可以是 packagePerson/pages/qixi/,但 app.json 里的 root 必须是独立顶级路径,例如 packageActivity,绝不能是 packagePerson/pages/qixi

一句话外卖

微信小程序只有「主包 → 分包」一级拆分,分包永远是叶节点,想再拆只能另起一个顶级分包,没有嵌套分包这条路。