一、微信小游戏分包加载机制
将游戏内容拆分成多个包,在首次启动时仅下载必要的“主包”,其余分包可在游戏运行过程中根据需要下载。
包大小限制
| 包类型 | 大小限制 | 说明 |
|---|---|---|
| 整个游戏 | ≤ 30MB | 主包 + 所有分包总和 |
| 主包 | ≤ 4MB | 游戏启动必需的核心资源 |
| 普通分包 | 单个不限 | 功能模块,如商城、新关卡 |
| 独立分包 | ≤ 4MB | 可独立运行的试玩模块 |
- 整个小游戏(主包 + 所有分包)总大小不超过 30MB
- 主包大小不超过 4MB
- 单个普通分包大小不限
- 单个独立分包大小不超过 4MB
独立分包
独立分包是小游戏中一种特殊类型的分包,可以独立于主包和其他分包运行。以独立分包路径启动小游戏时,客户端会仅下载独立分包并启动游戏,不会下载主包,以此实现部分场景下快速启动游戏的需求。
开发者可以按需将某些具有一定功能独立性的页面配置到独立分包中,可以很大程度提高页面打开速度。
➡️ 两种分包类型对比
| 特性 | 普通分包 | 独立分包 |
|---|---|---|
| 运行方式 | 依赖主包运行 | 完全独立运行 |
| 启动速度 | 首次需加载主包 | 极速启动,无需主包 |
| 使用场景 | 游戏主体功能模块 | 分享试玩、广告引流 |
| 代码隔离 | 可调用主包资源 | 完全隔离,自给自足 |
二、微信小游戏运行机制

在微信里打开一个小游戏时,过程大概是这样的:
1. 环境准备
当点击小游戏图标的瞬间,微信客户端会立刻为这个游戏:
┌─────────────────────────────────────────┐
│ 微信客户端(Native层) │
└─────────────────┬───────────────────────┘
│ 启动双线程模型
┌──────────┴──────────┐
▼ ▼
┌──────────────┐ ┌──────────────┐
│ 逻辑层线程 │ │ 视图层线程 │
│ │ │ │
│ 创建JS虚拟机 │ │ 创建WebView │
│ │ │ │
│ 注入wx API │ │ 创建Canvas │
└──────────────┘ └──────────────┘
- 启动逻辑层线程:创建一个全新的 JavaScript虚拟机(简称JS VM)实例(在iOS上是 JSContext实例,Android上是V8实例)
- 启动视图层线程:创建一个 WebView 实例(在iOS上是 WKWebView,Android上是 XWeb),并在其中创建一个全屏的 Canvas 画布
- 注入通信桥梁:在逻辑层JS VM中注入 WeixinJSBridge 和 wx API,使其具备与Native层和视图层通信的能力
🤔 JavaScript虚拟机(JS VM)是什么?
JS VM可以理解为是一个“与世隔绝的JS代码执行牢房,专门用来执行JS代码”。
“与世隔绝”:这是JS VM最关键的一点。这个牢房没有门,没有窗。在牢房里运行的JS代码,无法直接接触到外部的任何东西,比如:
- 无法直接操作手机的文件系统
- 无法直接调用手机的摄像头
- 无法直接发起网络请求
- 甚至无法知道隔壁牢房(另一个小游戏)的存在
为什么需要JS虚拟机?
为了绝对的安全和稳定。
如果小游戏的JS代码能为所欲为,那么一个恶意游戏就可以:
- 删除你手机上的照片
- 偷偷调用你的麦克风录音
- 让另一个游戏崩溃
- 窃取你在另一个游戏里的数据
JS VM 提供的沙箱环境从根本上杜绝了这些问题。每个游戏都在自己的沙箱里玩,谁也影响不了谁。
🤔 WeixinJSBridge是什么?
WeixinJSBridge 是那个“牢房里唯一的内线电话”。
既然JS代码被关在“牢房”里,它怎么才能实现登录、支付、振动这些需要与外界交互的功能呢?
答案就是通过这个唯一的内线电话——WeixinJSBridge。它是一个通信桥梁,连接着隔离的JS VM 和 强大的微信Native层。
“内线电话”:JS代码不能自己“伸手”出去拿东西,但可以通过这个电话请求外面的“警卫”(Native层)帮它做事。
🤔 二者的关系:如何协作?
JS VM 和 WeixinJSBridge 二者相辅相成共同构成了小游戏的安全运行体系。
它们的协作关系,以及我们开发者熟悉的 wx API 在其中扮演的角色,可以用下面这张图清晰地展示:

让我们用一个具体例子来走一遍这个流程:
目标:小游戏需要振动手机15毫秒。
牢房内(JS VM):你的游戏代码 Game.js 中有一行代码:
wx.vibrateShort({ type: 'light' });
这里的 wx.vibrateShort 就是你手上的 “电话指令手册” (wx API) 里的一条标准指令。
拨打电话(WeixinJSBridge):wx.vibrateShort 这个API方法的内部实现,其实就是拿起了 “内线电话” (WeixinJSBridge),并按照固定格式说:“喂,Native吗?帮我执行一下 vibrateShort 这个操作,参数是 {type: 'light'}。”
牢房外(Native层):微信的Native层(由C++/Java等编写)接到电话后,真正地去调用手机操作系统的振动API,让手机振动起来。
返回结果:振动完成后,Native层再通过 WeixinJSBridge 这个“电话”回传给JS VM里的代码:“事情办完了。”(通常以一个回调函数或Promise决议的形式通知)。
// 你的游戏代码中
wx.vibrateShort({ type: 'light' });
// 实际执行流程:
// 1. wx.vibrateShort调用WeixinJSBridge
// 2. WeixinJSBridge通知微信Native层
// 3. Native层调用系统振动API
// 4. 完成振动,回调通知JS层
总结对比
| 特性 | JS VM (JavaScript 虚拟机) | WeixinJSBridge (JS桥接器) |
|---|---|---|
| 角色 | 执行环境(牢房) | 通信工具(电话) |
| 主要功能 | 解释和执行JS代码,提供安全沙箱隔离 | 在JS环境和Native环境之间进行安全数据通信 |
| 对开发者可见性 | 透明,开发者感知不到它的存在,直接写JS就行 | 半透明,通常不直接操作它,而是通过封装好的 wx API来间接使用 |
| 关系 | 基础:没有JS VM,JS代码无处运行 | 通道:没有WeixinJSBridge,JS代码与世隔绝,无法实现复杂功能 |
你的小游戏代码运行在 JS VM 这个安全的沙箱里,并通过 WeixinJSBridge 这个唯一的桥梁与微信的强大原生能力进行通信。
而你平时打交道的 wx 对象,则是微信为你封装好的、用于操作这座桥梁的标准化工具集(wx API)。
关系:小游戏JS代码 -> wx API -> WeixinJSBridge -> 微信Native层 -> 操作系统
2、双线程模型

微信小游戏采用逻辑层与视图层分离的双线程模型:
- 逻辑层线程:负责执行游戏的JavaScript代码(如Game.js),处理游戏逻辑、数据、网络请求等
- 视图层线程:负责渲染游戏画面,本质上在小游戏中它只做一件事:管理并绘制一个Canvas画布
┌─────────────────────────────────────────┐
│ 微信小游戏架构 │
├─────────────────────────────────────────┤
│ 逻辑层(大脑) │ 视图层(画笔) │
│ │ │
│ • 执行JavaScript代码 │ • 管理Canvas画布 │
│ • 处理游戏逻辑 │ • WebGL渲染 │
│ • 数据计算 │ • 画面绘制 │
│ • 网络通信 │ │
└─────────────┬───────────┴────────┬───────┘
│ │
└───事件流与数据流────┘
双线程的具体实现技术:
| 平台 | 逻辑层执行环境 | 视图层渲染环境 |
|---|---|---|
| iOS微信客户端 | JavaScriptCore (iOS系统JS引擎) | WKWebView (iOS系统WebView) |
| Android微信客户端 | V8 (Chrome的JS引擎) | XWeb (微信自研渲染引擎) |
| 微信开发者工具 | NW.js (桌面JS运行时) | Chromium WebView (Chrome内核) |
微信小游戏需要运行在iOS、Android、PC等多个平台。微信通过封装底层差异,开发者使用的都是同一套JavaScript语言和wx API。
iOS上类似这样
逻辑层
// JSContext是JavaScriptCore框架中一个类
JSContext *gameLogicContext = [[JSContext alloc] init]; // 1. 创建一个JSContext实例
JSVirtualMachine *jsVM = [gameLogicContext virtualMachine]; // 这就是那个“JS VM”
// 2. 向这个JSContext中注入微信的能力
[gameLogicContext setObject: weixinBridgeObject forKeyedSubscript:@"wx"];
// 3. 加载并执行你的小游戏代码
NSString *gameJSCode = ...; // 你的 Game.js 等所有JS代码
[gameLogicContext evaluateScript: gameJSCode];
视图层
// 同样在微信的Objective-C代码中
WKWebView *gameView = [[WKWebView alloc] initWithFrame: CGRectZero]; // 1. 创建一个WKWebView
// 2. 加载一个非常简单的HTML页面,其中只有一个<canvas>元素
NSString *htmlString = @"<html><body><canvas id='gameCanvas'></canvas></body></html>";
[gameView loadHTMLString: htmlString baseURL: nil];
// 3. 将gameView的视图添加到当前窗口,但只显示它的Canvas部分
JS VM = JavaScriptCore 框架。微信用它创建了两个实例。
- 逻辑层线程 = 一个独立的 JSContext实例,运行你的 Game.js
- 视图层线程 = 一个隐藏的 WKWebView 实例,负责渲染Canvas
-
WeixinJSBridge = 一整套 Objective-C 与 JavaScript 互相调用的技术实现,包括:
- 向 JSContext 注入Native对象
- 使用 WKWebView 的 evaluateJavaScript: 和 messageHandlers
正是通过这种精妙的设计,微信在iOS平台上将苹果官方的组件粘合起来,构建出了与抽象架构完全一致的双线程安全模型。
Android的实现虽然技术细节不同(用V8代替JSCore,用XWeb代替WKWebView),但最终的架构和行为是完全一致的。
3. 下载与加载

环境准备好后,开始加载游戏内容:
下载游戏包:微信客户端根据你的地理位置,从最近的CDN节点按需下载游戏包。为了速度,它通常不会一次性下载全部,而是先下载一个核心启动包(game.js 和必要的框架代码)
-
加载引擎与代码:
- 首先加载小游戏适配器和游戏引擎的框架代码(如Cocos引擎库或Unity的WebAssembly模块和胶水代码)
- 然后加载你的业务逻辑代码(如 src 目录下的 Game.js, Player.js 等)
缓存到本地:下载的文件会被缓存在手机本地,下次打开游戏时极大减少下载时间
4. 初始化与启动
所有代码就位后,启动开始:
引擎初始化:执行引擎框架的初始化代码,引擎会通过
wx.createCanvas()获取Canvas画布,初始化WebGL上下文执行Game.js:这是小游戏的入口文件。微信客户端会主动调用其中定义的
onLaunch和onShow生命周期函数-
游戏主循环开始:
- 你的游戏代码(例如Cocos的
cc.game.run)开始执行,启动游戏主循环 - 逻辑层(JS VM)开始计算游戏世界状态:角色位置、物理碰撞、分数等
- 视图层(WebView)根据逻辑层传来的数据,通过WebGL在Canvas上绘制出一帧帧画面
- 你的游戏代码(例如Cocos的
事件循环:同时,微信客户端会持续将用户的触摸、手机传感器等事件,通过WeixinJSBridge传递给逻辑层,逻辑层处理后再触发视图层更新
总结一下:
┌─────────┐ ┌─────────┐ ┌─────────┐
│ 下载 │───▶│ 加载 │───▶│ 启动 │
├─────────┤ ├─────────┤ ├─────────┤
│ 1. 就近CDN │ │ 1. 引擎框架 │ │ 1. 引擎初始化 │
│ 2. 核心启动包│ │ 2. 业务代码 │ │ 2. 执行Game.js│
│ 3. 智能缓存 │ │ 3. 资源预载 │ │ 3. 游戏主循环│
└─────────┘ └─────────┘ └─────────┘
启动详细流程:
- 智能下载:从最近CDN下载最小必要资源包
-
分层加载:
- 先加载引擎适配器
- 再加载游戏业务代码
- 缓存优化:下载内容本地缓存,二次启动极速
-
初始化:
// 微信自动调用Game.js生命周期 GameGlobal.onLaunch(); // 游戏初始化 GameGlobal.onShow(); // 游戏显示 -
主循环开始:
- 逻辑层计算游戏状态
- 视图层渲染每一帧
- 事件系统处理用户交互
三、CocosCreator、Unity不同游戏引擎开发的游戏为啥能运行在微信小游戏平台?
游戏引擎的构建发布过程,不是简单的打包,而是一次深度的代码转换和接口对接。

1. Cocos Creator (TypeScript/JavaScript)
Cocos Creator 的转换过程最为“自然”,因为它本身就使用 TypeScript/JavaScript。
- 代码层面:你写的 .ts 脚本在构建时,会被编译成优化后的 .js 文件。这部分代码可以直接在小游戏的JS VM中运行
- 引擎层面:Cocos Creator 引擎库本身的代码(也是用 TypeScript 写的)也会被编译成 JavaScript,并一起发布
-
适配层:这是关键!Cocos Creator 内置了一个 “微信小游戏适配器”。这个适配器做了以下核心工作:
-
画布创建:使用
wx.createCanvas()创建游戏画布,而不是浏览器中的<canvas>元素 -
资源加载:将引擎内的
cc.assetManager等资源加载请求,转译成wx.request或wx.downloadFile等小游戏API -
文件系统:将引擎的文件操作适配到小游戏的本地文件系统
wx.getFileSystemManager() -
输入事件:将
wx.onTouchStart等事件,转换成 Cocos Creator 引擎能识别的cc.systemEvent -
音频播放:将
cc.audioEngine.play转成wx.createInnerAudioContext()
-
画布创建:使用
┌─────────────────────────────────────────────┐
│ Cocos Creator开发流程 │
├─────────────────────────────────────────────┤
│ 你的TypeScript代码 → 编译优化 → .js文件 │
│ │
│ Cocos引擎库 → 编译优化 → 引擎.js │
│ │
│ ╭──────────────────────────────────────╮ │
│ │ 微信小游戏适配器(关键桥梁) │ │
│ ├──────────────────────────────────────┤ │
│ │ • 画布创建:wx.createCanvas() │ │
│ │ • 资源加载:wx.request() │ │
│ │ • 文件系统:wx.getFileSystemManager() │ │
│ │ • 音频播放:wx.createInnerAudioContext()│ │
│ │ • 输入事件:适配触摸到cc.systemEvent │ │
│ ╰──────────────────────────────────────╯ │
└─────────────────────────────────────────────┘
优势:TypeScript原生支持,转换自然,性能损耗小
结果:你写的游戏逻辑代码几乎不用改,因为引擎和适配器帮你处理了所有平台差异。
2. Unity (C#)
Unity 的转换过程更为复杂,因为它涉及从 C# 到 JavaScript 的“跨界”转换。
核心技术:IL2CPP 与 WebAssembly
C#到C++:发布小游戏时,Unity 会使用 IL2CPP 技术,将你的 C# 代码和 Unity 引擎底层代码编译成 C++
C++ 到 WebAssembly:再将生成的 C++ 代码编译为 WebAssembly 字节码。WASM 是一种可以在现代浏览器(包括小游戏的WebView)中高效运行的低级语言,性能接近原生
JavaScript 胶水代码:Unity 会生成大量的 JavaScript “胶水代码”,这些代码负责:
- 加载和实例化 WASM 模块
- 在 小游戏的JS VM 和 WASM模块 之间建立通信桥梁
- 将 Unity 的渲染命令(如 OpenGL)转发给小游戏的 Canvas(通过 WebGL)
- 将小游戏平台接收到的事件(触摸、传感器等)传递给 WASM 模块中的游戏逻辑
适配层:与 Cocos 类似,Unity 也有一个针对微信小游戏的 Platform Abstraction Layer。它实现了 Unity 引擎期望的系统调用(如文件I/O、网络、音频)在微信平台上的具体实现,内部同样是调用了 wx.* 系列 API。
┌─────────────────────────────────────────────┐
│ Unity到微信小游戏转换流程 │
├─────────────────────────────────────────────┤
│ 你的C#代码 + Unity引擎 │
│ ↓ │
│ IL2CPP技术转换 │
│ ↓ │
│ C++中间代码生成 │
│ ↓ │
│ 编译为WebAssembly字节码 │
│ ↓ │
│ 生成JavaScript胶水代码 │
│ ╭──────────────────────────────────────╮ │
│ │ 微信平台适配层(PAL) │ │
│ ├──────────────────────────────────────┤ │
│ │ • 实现Unity引擎期望的系统接口 │ │
│ │ • 映射到wx.*系列API │ │
│ │ • 处理渲染命令转发 │ │
│ │ • 桥接WASM与JS环境 │ │
│ ╰──────────────────────────────────────╯ │
└─────────────────────────────────────────────┘
关键技术:
- WebAssembly:高性能字节码,接近原生性能
- JavaScript胶水代码:连接WASM模块与微信环境
- 平台抽象层:统一接口,屏蔽平台差异
结果:点击“发布为微信小游戏”,Unity就帮你完成了一系列复杂的转换和适配,生成一个可以直接在微信里运行的包。
总结:微信小游戏的设计
微信小游戏通过四大核心技术实现了安全、高性能的游戏体验:
- 分包加载机制 - 按需下载,平衡体验与内容
- 双线程模型 - 逻辑渲染分离,保障流畅稳定
- 安全沙箱 - JS虚拟机确保平台安全
- 统一适配层 - 让不同引擎游戏无缝运行
这套机制让开发者只需关注游戏内容创作,复杂的底层适配和性能优化由微信平台和游戏引擎共同完成,真正实现了"一次开发,多端运行"的理想状态。