# 活动 ZIP 分包与公共清单 金字塔、黄金矿工和百人赛统一接入。构建扩展位于 `packages/activity-bundles`,接入名单为 `bundles.json`:`pyramid`、`coin_madness`、`art`、`matching`、`stage1`、`stage2`、`stage3`。公共清单只描述资源,不包含活动开放时间、玩家资格或奖励状态。登录成功后提前准备全部受支持远程分包的磁盘缓存,活动开放判断、自动弹窗顺序和业务接口流程不变。 ## 构建与发布 1. 重启 Creator 2.4.15,使构建扩展注册。上述七个 Bundle 配置为微信远程 Bundle、合并所有 JSON;百人赛 `cloud_rise_home` 仍为本地分包。其他平台配置不变。 2. 在微信构建配置中填写 HTTPS 资源服务器地址,完整构建微信小游戏。扩展自动压缩接入名单中的每个 Bundle,生成 SHA-256、ZIP 大小及解压文件校验清单。 3. 默认发布产物在 `build/wechatgame-activities/remote/`:公共 `manifest.json`,以及七个 `/..zip`。同样输入重复构建,ZIP 和哈希不变。旧哈希 ZIP 保留,方便旧客户端和正在运行的请求继续读取。 4. 先上传哈希命名的 ZIP,确认文件可访问后,再更新 `remote/manifest.json`。清单禁用 CDN 缓存;ZIP 可长期缓存。代码包中的 `remote` 目录不上传到微信。ZIP 只含资源,组件脚本仍由 `src/scripts//index.js` 随微信代码包发布。 5. 同步发布本次客户端代码。后续只改资源可更新 ZIP 和清单;修改脚本或本地依赖仍需要重新发布小游戏代码包。本工具不自动上传或发布。 已有构建目录可单独生成资源包(不编译 TypeScript,也不能替代完整构建): ```powershell node packages/activity-bundles/pack.js build/wechatgame ``` 资源地址取自构建产物 `src/settings.js` 的 `server`,例如 `https://cdn.pay.nika4games.com/remote/manifest.json`。运行时不会把业务接口域名当成资源域名。微信需配置该 CDN 的 request/downloadFile 合法域名。 公共清单严格使用以下结构,每个 Bundle 仅包含 `file`、`hash`、`size`。`hash` 是整个 ZIP 的 SHA-256,`size` 为 ZIP 字节数。下面省略百人赛五个同结构条目;黄金矿工保留实际 Bundle 名 `coin_madness`: ```json { "schemaVersion": 1, "bundles": { "pyramid": { "file": "pyramid/pyramid.<哈希值>.zip", "hash": "", "size": 123456 }, "coin_madness": { "file": "coin_madness/coin_madness.<哈希值>.zip", "hash": "", "size": 234567 } } } ``` Bundle 配置文件名、版本及逐文件校验信息存于 ZIP 内的 `bundle-manifest.json`,不加入公共清单。下载后先校验整个 ZIP,再校验内部清单与归档文件是否一致;本地缓存记录保存内部清单哈希,防止内部清单损坏导致完整性检查失效。 ## 加载与缓存 `ActivityBundleLoader.ensureBundle("pyramid")` 接入 Cocos 的 Bundle 加载方式。微信构建扩展在 boot 前安装公共加载器,既支持该方法,也兼容既有 `cc.assetManager.loadBundle(name, callback)` 调用。编辑器和浏览器预览继续使用 Creator 原有加载方式。微信构建缺少加载器时明确报错,不悄悄退回远程目录下载。 - 登录成功时,`ActivityScheduleService.afterLogin()` 调用 `ActivityBundleLoader.beginCycle()`,立即请求公共清单并后台准备接入名单中的全部分包,与活动状态请求并行,不等待活动开放、不阻塞登录完成或进入首页。服务端清单额外列出的未知分包不会下载。 - 提前准备只执行缓存检查、必要的 ZIP 下载、校验、解压及缓存保存,不注册 Bundle、不加载 Prefab 或图片。每次最多准备两个分包;正式打开活动会优先处理该包尚未开始的任务,复用正在准备或已经准备好的结果,不等待其他分包全部完成。 - 登录至首次首页共享一个资源检查周期;之后每次返回首页、切回前台开启新周期并重新后台检查全部分包。一个周期内,各活动共享一个清单请求,同一 Bundle 共享磁盘准备和引擎加载任务;已准备好的文件不在打开时重复校验。持续停留和倒计时不发起网络请求。 - 首页依据活动日程、关卡门槛和已知个人完成状态预加载金字塔 Prefab;其他页面沿用原有引擎加载时机。打开活动复用日程,个人详情单独获取。 - 缓存按资源服务器地址、Bundle 名、ZIP 哈希隔离。哈希相同且每个文件的大小、SHA-256 和 Bundle 配置都正确时使用本地解压目录;缺失或损坏时重新下载。 - ZIP 先下载到新的暂存目录,核对大小、实际 SHA-256 和归档路径后解压,再验证文件和配置。目录按层级创建,父目录先完成,同层最多八个并发;失败停止派发并等待在途 mkdir 完成后清理。全部验证成功才更新该 Bundle 的缓存记录。失败只删除该暂存目录,不覆盖旧记录、不清除其他活动缓存。 - 清单请求、解析或校验失败时,允许使用本地缓存继续加载,但仍校验缓存归属、内部清单哈希及每个文件的完整性;没有有效缓存则失败,不猜测远端版本、不下载或改写缓存记录。同周期共享加载结果,下次返回首页或切回前台重新检查清单。正常清单缺少活动条目或 ZIP 加载失败时仍报错,不回退旧缓存。 - 活动页面与进行中的 Prefab 预加载持有资源引用。新哈希可先下载,但使用中的 Bundle 保持有效,引用释放后下次加载才切换。切换时清理本 Bundle 的旧内存资源,不调用全局清缓存。 - 后台准备失败按包记录,不影响登录和其他活动。正式打开该包时允许一次前台准备重试;前台失败继续在本周期共享失败结果,避免重复渲染造成下载循环。清单失败仍遵守同周期共享和下一周期重查规则。 - 只有一份本次客户端支持的接入名单;未来接入其他活动时添加 Bundle 名、接入其开放判断和页面引用生命周期,再完整构建。 百人赛五包作为一个依赖组:`retainGroup("cloudRise")` 只保留引用,不发起请求;`prepareGroup` 在原版本检查位置选择公共清单,本身不下载 ZIP。后台准备可以下载尚未打开的阶段,但不切换内存中的资源组。页面及在途加载持有期间固定该清单,即使返回前台也不会混用新公共美术和旧页面。所有引用释放后,下次资源检查可选新清单;正式激活新版本时依赖页先于公共美术释放。离线时只允许使用与上次保存的组清单一致且校验通过的缓存,缺包就失败。 黄金矿工在登录后的后台阶段准备磁盘缓存。点击入口、每日提醒、结算通知触发时,`acquireBundle` 复用准备结果后注册 Bundle;若尚未准备完成,则等待其剩余步骤,之后再加载 Prefab。关闭页面后等待在途主面板、说明、结算 Prefab 回调结束及节点销毁,再释放引用;不自行调用 `releaseAll/removeBundle`。 ### 黄金矿工冷缓存耗时排查 登录成功后即请求公共清单并开始磁盘准备。自动提醒在首页弹窗队列实际执行时获取 Bundle;已经准备完成时仅需引擎注册和主面板 Prefab 加载,未完成时会等待该包的剩余准备步骤。首屏数据请求与打开流程并行,面板需等待数据和资源均完成。 重新构建微信客户端后,`[ActivityBundles] init` 的 `diagnostics` 为 `login-preparation-v3`。按同次运行的 `name: coin_madness`、`cycle` 和时间戳查看: - `manifest.ready.elapsedMs`:公共清单请求及解析耗时;清单已被同周期其他活动获取时不会重复请求。 - `preload.start`:本周期全部分包后台准备启动;各包的 `prepare.ready` 表示磁盘缓存已经就绪,尚未注册引擎 Bundle。通过时间戳与 `engine.load` 对比可判断准备是否提前完成。 - `directory.timing`:`phase` 分别记录下载、读 ZIP、ZIP 校验、归档索引、建目录、解压、内部清单、逐文件校验、保存缓存;`elapsedMs` 为本阶段耗时,`totalMs` 为目录准备累计耗时。缓存命中则记录 `verify-cache`。 - `engine.ready.elapsedMs`:Cocos 注册 Bundle 耗时。 各条日志包含 `timeMs`,可在复制后继续对齐时序。Bundle 总耗时包含其内部阶段,统计时不要重复相加。源码计时变更需要重新构建客户端,单独上传资源 ZIP 不会更新这些日志。 ## 从旧版本迁移 `packages/cloud-rise-package/main.js` 不再注册构建钩子;旧打包工具仅保留供维护旧发布使用。新构建会移除旧 `cloud-rise-package` 启动注入以及已迁移活动的旧 subpackage 声明。`assets/cloud_rise/version.json` 不再控制新客户端资源版本,无需递增。 首次迁移必须完整构建并发布新微信客户端,不能只在旧构建上运行 pack。服务器保留旧 `remote/cloud_rise/version.json` 及原目录服务旧客户端,不用新发布覆盖它们。旧 Cocos 文件缓存由引擎管理,不全局清理;新 ZIP 缓存独立保存。 ## 业务接口请求时机 | 时机 | activityConfig/list | | --- | --- | | 登录成功 | 请求一次 | | 登录后的首次首页 | 复用登录中的请求或已取得结果 | | 从关卡等页面返回首页 | 请求一次,刷新通关后的解锁条件 | | 后台切回前台(包括关卡内) | 请求一次;首页与全局监听共享请求 | | 抽奖、领奖、支付确认成功 | 不请求;金字塔刷新 pyramid/api action:info | | 首页持续停留、倒计时变化 | 不请求,按服务器校准时间本地判断 | | 点击入口、资源预加载 | 复用日程,不额外请求列表 | 首次首页若登录查询失败或结果已失效,允许补取一次;在途请求始终合并。账号或环境变化清空个人日程,资源仍按资源服务器隔离,不按账号重复下载。 ## 本地验证 ```powershell node --test tools/test-activity-bundles.cjs tools/test-activity-resource-integration.cjs tools/test-pyramid-resource-loader.cjs node --test tools/test-cloud-rise-bundles.cjs tools/test-cloud-rise-prefab.cjs tools/test-cloud-rise-package.cjs node --test tools/test-activity-schedule.cjs tools/test-pyramid-entry.cjs tools/test-pyramid-home-reminder.cjs node tools/check-pyramid-types.cjs HEAD ``` 覆盖确定性 ZIP、SHA-256、全量后台准备与按需激活、准备并发上限与前台优先、目录并发及失败排空、缓存命中及修复、后台失败前台有限重试、下载/解压失败保留旧包、多活动/并发共享清单、环境隔离、前台新周期、旧请求延迟及活动页面持有期间更新。发布前还需在微信开发者工具与真机核对 CDN 配置和本地文件系统加载;Node 测试不能代替微信设备验证。