# 代码分包

## 概述

### 背景

unity 导出小游戏项目后，代码是在一个 wasm 文件里，经过 brotli 压缩后，放在 wasmcode 目录下

一般小游戏的 wasm 大小都为 30M 左右，压缩后为 6M 左右

启动阶段，小游戏需要先下载完 wasmcode 再编译，这里会占用较高的内存和启动时间，这对用户都是非常重要的指标。

因此我们提供了Wasm代码分包工具，将原来的 wasm 拆分为两个，一个用于启动加载（主包），另一个可以延迟加载（子包）

使得小游戏可以先加载较小的首包进入主场景，再异步加载剩下的分包。**大幅度降低下载时间和编译耗时（几秒）**。

另外对于iOS高性能模式，子包不会加载，会转为按函数粒度按需加载，从而**大幅度减少内存压力（200-300MB），减少崩溃**。

本文章将先介绍**操作步骤**，再介绍开发者长期迭代时所需关心的**核心指标以及问题**。

## 实现原理

目前我们采用了一种 Profile Guided Optimization 的方式，通过运行时收集信息，按函数粒度对小游戏的 wasm 代码包进行拆分

开发者可以在开发阶段，通过真机运行小游戏，并尽量覆盖游戏内的场景，特别是启动后最先进入的场景和关卡（比如新手教学，游戏最初的关卡内容）来**收集信息。**

工具上会显示收集到的函数个数，这时候就可以重新分包，将收集到的函数加入首包。

因此收集工作非常重要，收集的场景覆盖率越高，命中子包的时机就可以相应延后，使得首包可以满足大部分新玩家前几分钟的游戏进程

我们提供了一个微信开发者工具里的插件来辅助分包过程，依赖的[开发者工具](/miniprogram/dev/devtools/download.md)版本为 1.05.2104251 RC 及以上，稳定版 1.05.2105100 已支持。

分包技术会持续迭代，请确保使用**最新的分包插件以及Unity/团结引擎导出插件**，以获得最优的分包性能体验。

## 插件安装
通过开发者工具的设置-拓展设置-编辑器自定义拓展，安装 wasmCodeSplit 这个插件

![](https://res8.wxqcloud.qq.com.cn/wxdoc/4942bf27-3aa0-491c-bd34-1ac8008f4386.png)

## 插件更新

开发者工具上（如果用的是stable版，非minigame版）的插件一般是自动更新的

手动更新
![](https://res8.wxqcloud.qq.com.cn/wxdoc/c366f675-edcf-463d-9007-50e72522179e.png)

## 插件使用

分包插件按小游戏的md5（wasmcode下的wasm文件名里的md5）来区分不同的小游戏包

相同md5的小游戏包会复用同一份分包结果

对于新构建的小游戏包，分包流程如下：

* 点启用代码分包
* 输入当前项目版本描述
* 等待上传代码包
* 等待预处理
* 选择是否增量分包，然后下一步
* 等待第一次分包
* 进入正式分包阶段，先android收集，然后继续下一步
* iOS收集，然后继续下一步
* 选择生成profile或者release包，然后收集，这一步可以重复进行

最后一步这里已经可以随时上传体验版了

具体操作和注意事项如下

#### 启用分包

打开插件开关后，在目录树上的工具栏中，可以看到插件的按钮，如图所示，点击后即可进入插件页：
   ![](https://res8.wxqcloud.qq.com.cn/wxdoc/afd26543-9870-4e46-b652-521acbf7254c.png)

#### 输入版本描述
   ![](https://res8.wxqcloud.qq.com.cn/wxdoc/a7f1c41d-7ff7-430c-ae10-5c363e6382bd.png)

#### 等待上传文件
   ![](https://res8.wxqcloud.qq.com.cn/wxdoc/ad150c92-e5cc-470f-b9c2-76a8cf4d8328.png)

#### 等待预处理
   ![](https://res8.wxqcloud.qq.com.cn/wxdoc/d688bada-52e3-42c9-ba79-77b0ed111563.png)

**注意：如果出现红框中的提示，说明这里的状态更新已经中断，需要重启开发者工具**

这一步一般是分钟级的耗时，**如果等待超过10分钟，建议先重启下开发者工具**

#### 选择是否增量分包
   ![](https://res8.wxqcloud.qq.com.cn/wxdoc/48b21d8c-30ab-4f3a-a215-966d612b884e.png)

如果这个游戏之前的包已经有用过代码分包，没有比较大的代码修改的情况下（比如大范围的代码重构，更换引擎），可以使用增量更新，也就是选择之前的某个包作为参考

我们会对比前后两个包的symbol，把之前收集过的函数当做放到首包，即无需重复收集

因此要求前后两个包都必须提供symbol文件

**在unity侧使用微信插件导出时，需要开启profiling func**，这样打包时就会导出symbol文件（webgl.wasm.symbols.unityweb）

**无需担心开启profiling func导致的包体增大，分包工具会优化函数名**

#### 等待分包
   ![](https://res8.wxqcloud.qq.com.cn/wxdoc/77ab0024-dc4c-4784-b975-f02b15a195f9.png)

#### 
android收集 + iOS收集

   ![](https://res8.wxqcloud.qq.com.cn/wxdoc/a7708ef6-2143-45f4-997a-c9a26d427eb1.png)

分包的收集，一般需要android和iOS单独收集

收集操作：
- 点击开发者工具的预览（**注意是预览，不是真机调试**，在真机上跑游戏，覆盖尽可能多的场景
- 当插件页显示的收集到增量函数个数相对稳定时，可以点击“我已收集好，继续下一步”

这里主要关注首包函数个数，一般跑完这两个步骤首包函数占整包函数个数的30%以上就差不多了

#### 重复收集与生成

android和iOS收集完，基本就可以测试和发布了

有条件的话，可以尽量覆盖各种机型(主流品牌)再多跑几次收集

每次收集发现新增函数趋于稳定之后，就可以继续点生成profile分包或者生成release分包

每次点生成时，会先跳到前面的等待分包界面，完成后再回来

#### 函数名获取与手动上报

为了方便开发者分析首包函数来精简代码，提供了“已收集函数名获取”和“手动上报”的能力。

点击“获取首包函数名和新增函数的函数名”会下载并打开两个txt文件分别包含首包函数名和新增函数名。

点击“选择函数名文件手动上报”即可选择之前下载的函数名文件上报（上报格式参考获取函数名时的文件格式），方便在切换 appid 后也能实现增量分包，也可以针对自己游戏预先准备好一份函数名文件（除非确定需要，否则不建议）手动上传来节约人工运行收集函数的时间。

![函数名获取与手动上报](https://res8.wxqcloud.qq.com.cn/wxdoc/8d316268-9a2f-4768-aab2-7bf5473a7957.png)

**每次生成会当前的分包version会加1**

### 关闭分包

如果想回退到未分包的版本，点击关闭代码分包即可

### 注意事项

上线前
* 生成release版分包
* `首包函数个数`至少要有原始包函数总数的30%
* `新增收集函数个数`清零
* 关注android或者iOS普通模式的子包是否过早加载（是否有`wait for func`的日志）
* 关注iOS高性能是否有`fetch js`相关的日志

如果有最后两点，那就还要继续收集+生成分包

上线后

* 小游戏包先不要删掉
* `新增收集函数个数`这个数据非常重要，要尽量保持关注，包括上线后

如果上线后，有玩家遇到新增函数个数，分包插件上也会更新（主要来源是iOS高性能），或者收到小游戏数据助手的相关告警，这个时候要继续生成分包，同时提审发布

# 分包关键信息

## 分包基本信息

这里介绍基本分包的信息，具体使用见分包流程。

![basic-info](https://res8.wxqcloud.qq.com.cn/wxdoc/f2ede2ff-0c0f-4d1c-baff-016f9d8f2088.png)

以上展示了分包的基本信息：

当前分包版本：profile包用来收集，release包用来发布。profile包千万不能发布上线，性能和内存表现非常差。

当前项目AppId：为当前分包小游戏的AppId。对同一个AppId的任何分包操作，都将排队进行，如果团队内有同时开发，可能会出现突然耗时很长的情况，请耐心等候。

当前插件版本：Unity启动插件版本。对应game.json中的UnityPlugin。它并不是分包插件的版本。分包插件的版本在插件扩展页面可以获取。

当前后台服务版本：为分包的技术版本，代表不同的分包技术，越新越好。截止文档攥写时，分包技术版本最新为7

当前代码md5：为小游戏项目的唯一标识，相同的md5被识别成同一分包项目。若Wasm不同但md5相同（开发者人为修改才会出现），则也会被视作同一个项目。若想对同一个小游戏项目重新预处理分包，则可以修改代码md5或者重新导出游戏包。

当前分包version：代表第几次分包。第一次分包为version 0，第二次为1，以此类推。

已经开启优化项：为空则表示没有开启任何优化项。这个优化项可以在“微信优化项”勾选。

原始包函数总个数：开发者原始Wasm包的函数个数。

当前首包函数个数：当前首包Wasm中函数的个数。

新增收集函数个数：本次收集中发现未在首包的函数。

微信优化项：对Wasm的运行表现进一步优化。开发者需要知道，这些优化项只会在部分场景有优化效果，请阅读相关说明，并自行比对优化效果。

已收集函数名获取：获取首包函数，以及新增收集的函数名字。

选择函数名文件手动上报：若开发者预先知道哪些函数一定要收集，则可以构造一个函数名文件，格式参考“已收集函数名获取”文件格式。请注意，过量的收集会膨胀代码提及，增大内存压力。请确保手动上报的函数一定需要收集。

关闭代码分包：将代码包从分包状态复原为原始小游戏包文件状态。如果需要恢复到分包状态，请开启分包并重新下载分包文件。

## 分包项目结构

分包项目结构如下：

![file-structure](https://res8.wxqcloud.qq.com.cn/wxdoc/dd70dbee-3a05-4bc0-8b74-d39d8eab1a0c.png)

以上展示了分包的基本结构，我们主要关注以下文件：

wamcode：分包前，这是原小游戏Wasm包。分包后，是首包/主包。这是一定会被加载且首先被加载的Wasm。

wasmcode1：这是安卓平台的子包，不会一开始就下载以及加载，而是在游戏运行后一段时间，自动加载。或者缺失函数的时候再加载。

wasmcode2（可选）：部分分包技术下，会有该分包，为iOS平台的子包，不会一开始就下载以及加载，而是在游戏运行后一段时间，自动加载。或者缺失函数的时候再加载。

webgl.wasm.symbols.unityweb：这是symbols文件，用来还原每个函数id对应的函数名，请保留，有需要的时候查看。

分包后项目大小会膨胀，这是正常的。分包需要一些辅助的文件，但只有首包（wasmcode）一定会加载，其他的则会延迟或者按需下载，对运行几乎没有影响。

首包的大小在3-5MB，子包在7-15MB，wasmcode+wasmcode1+wasmcode2在10-25MB内。

## 微信优化项

分包集合了许多定制的优化项，与游戏特征有关，按需选择。目前仅在“后台服务版本：6”及以上支持选择开启特殊优化，同时依赖开发者的分包插件和Unity导出插件等版本。如有需要请更新分包插件和Unity/团结导出插件的版本至最新，获得最好的性能体验。
- **profile包性能优化**：分包后台服务版本大于等于6。会修改函数调用上报的记录方式，使得运行性能接近 release 包，提高收集函数的效率，并且不存在什么负面影响，默认开启。
- **函数量优化**：分包后台服务版本大于等于6，且unityPluginVersion≥1.2.69时支持该优化项，但默认不启用。可以进一步减小分包后的wasm包中的函数量，从而减小编译内存占用。该优化项与游戏代码特征有关，更适合存在大量调用频率非常少函数的游戏，对运行性能有0～5%负面影响，内存占用降低0-50MB，**需要游戏自行测试收益并选择**。函数量的减少并不反映在分包面板上，但实际函数有一定减少。
![微信优化项](https://res8.wxqcloud.qq.com.cn/wxdoc/8e5ef6a8-e823-4236-ada0-487adf00c9fe.png)

## 评估分包状态

开发者在函数收集/上线后，都需要关心分包是否到位，并做出及时反映。平台也在探索更易用的交互和体验方式，优化开发者体验。

### 上线前的分包收集

开发者需要关心自己分包是否到位，可以用以下方法评估分包状态：

函数收集需要保障启动时刻的函数收集，在启动和游玩的前期，是用户最容易流失的时候（前30-45s），必须保证函数完全不缺失，否则缺失会造成卡顿，影响游玩体验甚至启动速度。

通过vConsole以及日志中，是否有wait for func 或者 fetch js:等函数的日志，来判断当前是否出现了函数的缺失。同时当画面出现一卡一卡的，或者突然卡死，需要考虑当前是否出现了函数的缺失。

同时，我们还可以关注一些对应的日志，例如“首次拉取js函数：xxms”表示首次缺失函数的时间，如果在45s内，就是收集不够。还有，“在callmain完成前fetchjs”日志，表示函数缺失甚至在引擎启动阶段就出现了，这会极大影响游戏的启动时间。

如果收集过程中出现了这个问题，需要及时收集，并重新分包，保证这些函数都在首包内。

由于不同机器有一定差距，因此也会出现一个机器收集后，另一个机器出现缺失。这是正常的，开发者需要根据实际情况，例如线上启动时间的变化等，选择是否需要重新收集/分包/上线。

越多的函数在首包，首包就会越大，启动时间和占用的内存也会越多，但就现在游戏的经验来看，收集的越多越好，因为大部分的函数是不会被收集到的，分包的优势仍然非常大。但请开发者不要盲目手动上报一些不缺失的函数，这样也会影响性能表现。

如果开发者发现，自身的游戏，在不同场景上，运行到的函数数量有巨大的差别（上万个函数差别），统一打包到首包会使得首包特别大，请联系小游戏助手，获取技术上的帮助。

一般来说，函数首包收集在25～50%比较正常，一般就是35%左右。

### 上线后的缺失/收集/补救

需要首先强调的是，Profile分包严禁上线，性能有非常大折损，请用Release分包上线。

我们在线上的分包运行时，也插入了比较稀疏的上报，能够在线上缺失的时候自动收集函数。

因此，游戏上线之后，开发者仍然能通过分包面板，看到自身的新增函数个数。

新增的函数是否会影响线上的表现，有一定讨论空间。如果这个新增的函数在启动前期，那么就算只有几个函数，也应该立刻收集并重新发布。

微信分包平台为保证用户的体验，采取了Patch包机制，自动的根据收集的新增缺失函数，生成Patch包，自动修复缺失函数。但是，这与机器的系统版本、网络环境、分包插件依赖组件的版本等有关。因此，如果使用老的分包插件，或者老的Unity/团结引擎导出小游戏，可能无法使用该功能。而且，就算支持，也并不一定能成功在所有的游戏玩家设备上加载，Patch包也有上限大小，因此我们主张开发者在函数量过多（100以上）的时候，主动进行分包，并重新上线。

对于长期迭代的开发者来说，还会使用增量分包。但增量分包是基于函数名进行匹配的，而由于原函数到Wasm函数，有较长的一段编译器生成距离，因此同一个函数没有进行任何改动，其名字和结构仍然有可能变化。最终，**增量分包并不一定会完全覆盖原有的所有函数**。我们主张开发者应该尽可能**保障前45s的启动黄金期**，保证函数在首包内。后面的函数缺失，如果函数symbol文件差异非常小，则可以采用更为高效的收集方式。

## CI工具
wasm代码分包作为微信开发者工具的插件，需要开发者在微信开发者工具中手动操作，在高频发布场景下效率偏低

因此我们提供wasmsplit-ci工具，可以不打开微信开发者工具，独立使用进行分包的各种操作（真机收集除外），供开发者集成到ci流水线上

### 功能
wasmsplit-ci目前提供以下能力：
- 打开分包
- 生成分包
- 获取分包信息
- 关闭分包

建议使用场景:
- 大版本开发阶段：按新增函数阈值定期生成profile包
- 小版本（代码无修改或无新增函数）或者bugfix阶段：直接走增量分包生成release包

### 准备工作
#### 密钥配置
wasmsplit-ci的使用需要传入密钥，需要在mp管理端-开发支持-研发工具箱-密钥管理-Wasm分包CI鉴权配置密钥
### 命令行调用
#### 安装
通过npm获取
```
npm install -g wasmsplit-ci
```
#### 支持命令
打开分包
```
Usage: wasmsplit-ci init [options]
init miniprogram
Options:
  -p, --project-path <projectPath>                
      project path, 小游戏项目的路径, 必填
  -k, --private-key-path <privateKeyPath>         
      private key path, 私钥文件的保存位置, 必填
  -d, --version-description <versionDescription>  
      version description, 版本描述
  -r, --refer-md5 <originalMd5>                   
      original code md5, 历史代码包md5
  -h, --help                                      
      display help for command
```
init命令会检查当前项目（appid+code_md5）的分包状态，完成必须的前置准备工作

**流水线每次执行**都需调用init命令进行初始化操作

**如果本次流水线需要增量更新**则需传入供增量参考的游戏包的md5

增量更新必须在项目首次分包时使用

示例
```
# 首次分包，需要增量分包
wasmsplit-ci init -p ./minigame-dir/ -k ./ci-privatekey -d "v1.0.0" -r $REFER_MD5
# 非首次分包，或者首次但不需要增量分包
wasmsplit-ci init -p ./minigame-dir/ -k ./ci-privatekey -d "v1.0.0"
```
查看当前分包信息
```
Usage: wasmsplit-ci getinfo [options]
get minigame function info
Options:  -p, --project-path <projectPath>         
      project path, 小游戏项目路径, 必填
  -k, --private-key-path <privateKeyPath>  
      private key path, 私钥文件路径, 必填
  -h, --help                               
      display help for command
```
getinfo获取信息，并以json格式保存在"$projectpath/.plugincache/codesplit/gameinfo.txt"中。

getinfo的json字段说明

| 键 | 说明 |
| --- | --- |
| isProfile | 当前分包版本(profile或release) |
| appid | 当前项目AppId |
| md5 | 当前代码md5 |
| subVersion | 当前分包version |
| apiVersion | 当前后台服务版本 |
| sourceFuncNum | 原始包函数总个数 |
| increaseNum | 新增收集函数个数 |
| currentNum | 当前首包函数个数 |

示例
```
wasmsplit-ci getinfo -p ./minigame-dir/ -k ./ci-privatekey
```
生成分包
```
Usage: wasmsplit-ci dosplit [options]
split minigame package
Options:  -p, --project-path <projectPath>         
      project path, 小游戏项目路径, 必填
  -k, --private-key-path <privateKeyPath>  
      private key path, 私钥文件路径, 必填
  --release                                
      release, otherwise profile, 是否release分包
  -h, --help                               
      display help for command
```
有新增函数即可调用，命令执行成功后会**下载分包结果，应用到minigame-dir目录**，执行失败可重复执行

生成分包后，可随时上传体验版

示例
```
# profile
wasmsplit-ci dosplit -p ./minigame-dir/ -k ./ci-privatekey
#release
wasmsplit-ci dosplit -p ./minigame-dir/ -k ./ci-privatekey --release
```
关闭代码分包
```
Usage: wasmsplit-ci disable [options]
disable code split Options:
  -p, --project-path <string>  project path, 小游戏项目路径, 必填 
  -h, --help                    display help for command
```
disable命令用于关闭代码分包，和插件的关闭代码分包作用相同

示例
```
wasmsplit-ci disable -p ./minigame-dir/
```
### 流水线示例流程
![alt text](https://res8.wxqcloud.qq.com.cn/wxdoc/a9b8679f-e7f8-4c02-8ba9-2f01e4e18ed4.png)
### 注意事项
- 此工具不能完成真机收集过程，真机收集仍需开发者单独执行
- 分包工具CI不提供预览及上传功能，可以使用微信开发者工具CI进行预览
- 请不要将密钥配置文件（id_rsa.conf）放在小游戏项目下，这会导致密钥文件一同被上传
- 日志文件保存在$projectpath/.plugincache/codesplit/log目录下，使用两个文件滚动保存(latest.log和backup.log)，每个文件保存最大容量为5M
- 如需更改appid,自行修改项目路径下project.config.json文件中的appid

### 常见问题排查
- 错误码:-10000401 密钥检验失败，请检查密钥是否正确 验签失败，请检查公钥私钥是否匹配
- 出现"need retry task: retryInit"之类的日志后中断执行，如果不是私钥路径错误的话，一般是私钥格式不对，私钥和MP配置的公钥都需要是PEM格式的。
- 使用CI分包后，miniprogram-ci上传时报错"main package source size 4369KB exceed max limit 4096KB"，需要更新miniprogram-ci到beta版2.1.14。

## 排查/反馈分包问题

分包运行时问题排查时，需要重点关注用户设备的运行环境，在遇到问题的时候应该要确保预先排查：
- 问题形式：问题的发生形式，例如：启动失败、加载失败、运行时错误等。
- 问题时刻：问题发生在哪个阶段，例如：启动、加载、运行等。
- 问题特征：问题发生与什么环境有关，例如：设备类型、系统版本、网络环境等。
- 是否复现：问题是否可以复现，用户遇到的量级有多少。例如：是否是随机事件，是否是用户操作导致的。

开发者自身不进行预先排查的，小游戏技术支持很难帮助开发者排查问题。

当开发者仍然无法定位和修复问题的时候，可以联系[小游戏技术支持](IssueAndContact)，在必要的时候，开发者需要提供游戏导出的项目文件协助排查。。

### 分包运行时问题排查

基础库版本和设备信息见vConsole或者日志如下：
![基础信息](https://res8.wxqcloud.qq.com.cn/wxdoc/5051d243-745d-4554-852e-71a90ce3c32a.png)

分包插件及相关信息见如下：
![插件信息](https://res8.wxqcloud.qq.com.cn/wxdoc/66040265-ae10-4bbf-8167-75eba3ac1126.png)

分包流程运行步骤见如下：运行过程可以参考 [启动流程](Startup)
![alt text](https://res8.wxqcloud.qq.com.cn/wxdoc/70d097ff-b4d9-4ce7-93b5-30805372352f.png)

除了直接看vconsole，还可以导出日志文件，然后分析日志文件。
![alt text](https://res8.wxqcloud.qq.com.cn/wxdoc/df66736b-0618-4636-a1f3-f817bce215e8.png)

# FAQ

## 分包开发过程

### 分包是否是必要的

对于 iOS 高性能模式，由于内存限制，游戏加载完整 wasm 基本就会内存 crash。分包能降低内存占用，同时我们对子包支持按需加载，才让游戏能稳定跑起来

所以如果是使用了 iOS 高性能模式则是必须的

对于 android 和 iOS 普通模式，分包主要目的是优化启动加载，另外这两个 runtime 下由于子包可以全量加载，因此对游戏运行影响最多只有加载子包的一次性影响

我们也会在启动 callmain 后 30s 提前加载子包，在这个时间之后才触发未收集函数的情况也不会有加载子包的影响

### 收集到什么时候可以结束

按照我们经验，一般首包函数有整包个数的 33%以上的时候就可以接受了，当然能尽量再收集完善刚好，个别游戏可能会接近 50%

这时候不代表没收集的函数都没用了，实际上有些函数可能只是调用比较冷门，后续还是可能会被调到，可以通过分包插件面板的`新增收集函数个数`来留意线上新增的情况，

如果线上新增较多（超过 50），可以考虑再往下分一次包然后提审发布

### 游戏内容难以遍历完整怎么办

我们针对这种情况也有线上patch可以进行补漏，但是patch有大小限制

建议新增收集函数个数超过100个的还是要生成新分包+发版本

### 分包总大小比原始包大/我的代码包分包后膨胀了很多怎么办？

这是正常现象。分包需要一些辅助的文件，但只有首包（wasmcode）一定会加载，其他的则会延迟或者按需下载，对运行几乎没有影响。

首包的大小在3-5MB，子包在7-15MB，wasmcode+wasmcode1+wasmcode2在10-25MB内。

1. 分包的目的主要是将启动时需要的包减小，一般分包后wasm首包可以控制在原包的1/3到1/2之间
2. 子包是有延迟加载的，因此耗时上不需要看总的大小，看首包的减少量即可
3. 一般iOS高性能模式才有内存使用瓶颈，而iOS上子包是按需加载的，可以缓解内存问题
因此，这里不需要关注分包后所有wasm包的总和，主要关注wasm首包（即minigame/wasmcode）的大小即可

### 为什么这次我分包之后多出来了一个wasmcode2

在新的分包技术版本中，我们为iOS引入了wasmcode2子包，按函数加载缺失的函数，提升用户的运行时体验以及优化开发者的函数收集效率。因此，游戏的代码包空间会有一些膨胀，且游戏运行时内存会增加～10MB左右。wasmcode2与wasmcode1的加载逻辑不同，wasmcode2在iOS上和老版本基本保持一致，还是函数粒度按需加载的，wasmcode1在安卓上是完整加载。这样保证了iOS上内存变化基本无感。

### 新增收集的函数要重新再次提审才会在首包吗

对的，用户下载的代码包只能是提审发布过的

### 会不会最终跑到所有函数都收集的情况

目前还没出现这种情况，超过整包 50%的都很少

大部分游戏收集 1 小时的函数个数都在 33%到 50%之间

可以等收集函数超过 75%了再来考虑这个问题

### Profile分包可以上线吗？

不可以！性能有非常大的劣化，在内存和帧率上都表现很差，玩家体验很差。

目前由于发布时无法获取分包信息，暂无法拦截profile包上线，请不要尝试上线profile分包。

### 没有看到增量分包的界面

由于增量分包是新增的功能，因此之前的项目不能被用来增量更新。更新分包插件后，第二次导出的版本开始才可以使用

### 增量分包没生效

请检查指定参考的旧版本以及当前版本是否都有 symbol 文件，以及是否有更换引擎或者其他导致代码变动较大的操作

### 如何更新分包插件

微信开发者工具会自动更新分包插件，一般不需要手动更新。可前往**微信开发者工具-编辑器区域-拓展列表**查看插件版本确认是否为最新版本

> 请勿使用小游戏版微信开发者工具，会出现插件无法正常更新或安装。请前往：适配文档-安装与使用，下载stable版本微信开发者工具。

![](https://res8.wxqcloud.qq.com.cn/wxdoc/9aae25ce-4f61-48e4-86ac-718553ec81e7.png)

### 分包插件安装失败

**首先确认是否为stable版本开发者工具。**

有两个地方可安装插件:
1. 编辑器区域-拓展：搜索wasm-code-split，点击安装
2. 菜单栏-设置-拓展设置，找到wasmcodesplit，点击进入详情页，点击获取

### 分包插件卡住

遇到流程卡住问题，一般先尝试关闭分包，然后重启开发者工具，再打开分包，大部分时候有奇效

### 如何查看分包插件日志
当出现问题时，优先排查是否stable版本的微信开发者工具，能解决大部分问题。
若问题仍无法解决，可[联系我们](IssueAndContact)，提供日志排查。
日志获取方式：
> 菜单栏-微信开发者工具-调试-调试微信开发者工具，搜索关键字：extension host。可右键保存日志文件

### 为什么我的预处理/分包时间特别慢？

可能是同一个appid提交过一次预处理，正在排队。请确保一次预处理结束之后再进行其他分包操作。

分包的时候，如果开发者还在同步收集函数，分包过程会重试，以将该阶段收集的函数均纳入进入。若开发者一直在分包的时候收集函数，会一直重试，直到收集完成，过程可达数小时。

至于预处理，其耗时比正常分包长，长的可能到20-30分钟，分包则5分钟（release显著更长）。若超过再怀疑是否时间过长。

重新导出游戏包或者更换md5，若多次仍如此，联系技术人员，怀疑该Wasm包分包不适配。

重试频率不能太快，预处理要排队，多次重试，会依次执行。

### 分包下载经常出错/分包经常中断

检查本地网络状态。

## 运行时过程

### iOS 高性能模式收集很卡

iOS 高性能模式由于加载子包的实现不同，刚开始收集时又基本是跑子包函数，所以最开始的收集会比较卡

这个时候可以观察分包插件面板，如果能看到有新增函数个数的变化，一般就是没问题的。如果出现卡顿（并且有新增函数）或者新增函数较多（超过 50），可以先继续往下生成分包，再进行收集。游戏运行会随着收集越来越流畅

### iOS 高性能模式代码分包后内存反而变得很高

这种情况一般是太多新增函数（比如几百个），iOS 高性能模式的子包代码也会占用大量内存，可以继续生成分包，将这部分函数放在首包（放首包的内存占用相对小些）

### OS 高性能模式出现 import section's count is too big

新版的插件已经规避这个问题，更新插件即可

### 微信开发者工具无法运行/Wasm编译卡住

如果出现以下问题：
- Wasm编译卡住： `still waiting runDependencies, ids=  ["wasm-instantiate"]` 这类错误，可能是因为Wasm包过大，真机没有这个问题。
- Wasm特性不支持：`WebAssembly instantiate(): unexpected section ‹Exception›` 这类错误，是因为开发者工具的Wasm虚拟机暂时不支持。

![](https://res8.wxqcloud.qq.com.cn/wxdoc/dbf06c03-5f74-4c5d-b709-d1d69c50b19f.png)

如果需要模拟器调试请安装2.0x以上的微信开发者工具的Electron Nigthly版本或者1.06版本，截止2026.06还没有在最新的稳定版本支持。

### 分包后程序无法运行

分包过程中会反复触发Wasm包下载/更新，开启/关闭分包的时候也会应用/恢复项目包的关键代码。如果在这个更新过程中对项目文件进行操作可能触发编辑不完全/重复/冲突等情况。一些可能的分包过程中的冲突操作如下：

1. wasmcode中的文件名和game.js中的Code Md5指定不一致。
2. wasmcode文件夹中存在多个wasm.br文件
3. 开发者工具模拟器无法运行：请确认真机是否可以运行。iOS和安卓以及模拟器是三种实现方式，在少部分接口上有差异。
4. 分包后缓存没有及时更新，可以清除模拟器缓存（如下图）

![](https://res8.wxqcloud.qq.com.cn/wxdoc/5d579dcc-5118-4259-b1e5-3060fbe509ab.png)

一个可能的分包错误如下：

![](https://res8.wxqcloud.qq.com.cn/wxdoc/879997ad-1e38-4e79-ad2b-a07ffc547cc2.png)

### iOS15.4报错：或偶发白屏闪退、内存不足闪退

iO（https://bugs.webkit.org/show_bug.cgi?id=237180）iOS 15.4（及15.4.1）存在一个严重的 WebKit 内核 Regression 漏洞。该漏洞导致 Safari 浏览器和微信 iOS 客户端在解析和编译大型 WebAssembly (Wasm) 文件时，JIT 引擎（或流式编译器）会出现偶发性的内存对齐与堆栈损坏错误（如报出 Out of bounds memory access、corrupted address 0 或 function not found 等错误）。特定代码意味着和代码特征有关，并不是所有Wasm都会出现。

可能现象：
```
2025-9-26 9:14:28 [warn] Could not allocate memory: System out of memory!

Trying to allocate: 3196395193B with 16 alignment. MemoryLabel: TempOverflow

Allocation happened at: Line:xxx
```

Unity社区讨论了这个问题（https://discussions.unity.com/t/ios-15-webgl-2-issue/857077/81?page=50），可以参考其解决方案。
- 先通过报错堆栈，找到对应函数。
- 然后使用条件编译指令，在特定关键函数（如涉及深层泛型迭代或大数组对齐的函数）上方加入 #pragma clang optimize off（并在函数结束后使用 #pragma clang optimize on）。

### WebAssembly相关接口不存在

WebAssembly相关接口不存在（如WebAssembly.instantiate）

用户的iOS可能启用了锁定模式，因此该接口被锁定

https://support.apple.com/zh-cn/105120

![](https://res8.wxqcloud.qq.com.cn/wxdoc/56617deb-b17d-4cf1-bccd-71d2c41ccc76.svg)文档变更日志（2条）
2026 年 06 月 08 日文档描述优化：iOS15.4 Bug的解决方案
2026 年 06 月 08 日分包wasmcode2 Q&A
