# 01 · 前端架构与运行环境 本篇建立**全局认知**:前端跑在什么环境、由哪几层构成、新旧两套架构如何并存、文件按什么顺序加载。 > 举例以麻将为主,但 `gameabc-framework` 是游戏中立的通用框架,本篇机制对任意子游戏一致。 --- ## 1. 运行环境 - **部署形态**:前端是**浏览器静态资源**,由 gameabc 引擎(`js/vendor/gameabc.min.js`)驱动,绘制基于精灵(Sprite)/图层(Layer)/群组(Group)的 2D 画面。不走 npm 构建。 - **与服务端**:通过平台网络层收发 JSON 包(`{app, route, rpc, data}`),全程异步。**服务端权威**——所有核心运算与胜负裁定以服务端为准、数据以服务端为权威;**前端只做界面展示与玩家交互**,本地保存的数据只是「用于渲染的副本」,不做权威计算(前端渲染与交互范式见 02,红线见 05)。 - **ES5 强制**:线上浏览器/平台不保证 ES6+。全部 JS 必须严格 ES5——用 `var`/`function`,对象继承用 `Object.create`,禁 `let`/`const`/箭头函数/模板字符串/`class`/解构/默认参数。 - **少量 Node 仅用于测试/工具**:`shared/` 算法可在 Node 跑单测,`scripts/` 是 Spine 数据构建脚本;线上运行时无 `require`,跨文件一律按**全局名**引用(各文件用 `var X = ...` 暴露全局,`index.html` 顺序加载)。 --- ## 2. 三层结构:平台 / 框架 / 子游戏 ``` js/vendor/ 第三方与引擎(禁改) gameabc.min.js gameabc 引擎原生 API jquery / spine-canvas.js js/00_Surface/ 前端平台代码(禁改) Const/Data/Desk/Func/Game/GameUI/Logic/Net/Player/Utl_* ... js/gameabc-framework/ ★ 通用模板框架(游戏中立,可复用) core/ GameABCUtils(唯一直连引擎)、SpriteManager(业务级精灵 API) system/ EventBus、AnimationManager、AudioManager ui/ BaseComponent、UIManager、SpriteCopyUtils、DynamicSpriteList spine/ SpineMgr templates/ *.template.js(派生子游戏时复制填充的模板) js/01_SubGame/ 子游戏前端 00_/01_/02_SubGame_*.js ★ 受限对接层(平台入口,尽量不改) codes/ ★ 子游戏实例(单向依赖框架;内部结构由子游戏自行组织) shared/ 前后端共享算法(服务端为权威源,同步而来,只读) ``` > `codes/` 内部如何分目录、如何命名文件,均由子游戏自行决定,本套文档不作规定;唯一例外是 `shared/`——它是服务端共享算法的同步副本,前端只读(见 05)。 依赖方向是**单向**的:`01_SubGame/codes` → `gameabc-framework` → `gameabc.min.js`。框架**不反向依赖**任何子游戏(见 03/05 的「框架中立」)。 --- ## 3. 新旧两套架构并存(重要) 前端当前**两套架构并存**,理解边界才不会改错地方: | | 旧架构(受限对接层) | 新架构(gameabc-framework + codes) | |--|----------------------|--------------------------------------| | 位置 | `js/00_Surface/`、`01_SubGame/00_/01_/02_SubGame_*.js` | `js/gameabc-framework/`、`01_SubGame/codes/` | | 角色 | 平台框架的**固定入口**,承接平台事件 | 子游戏真正的渲染/逻辑/网络实现 | | 可改性 | 平台代码禁改;受限文件不新增接口、尽量不改 | 在此自由开发 | **对接方式**:平台事件先进旧的 `Game_Modify.*` 入口,旧入口**只做转交**,把数据委托给新架构处理(详见 04): ``` 平台 → Game_Modify.appStart() → 启动初始化 启动 平台 → Game_Modify.StartWar(_msg) → 开局处理 开局 平台 → Game_Modify._ReceiveData() → 收包分发(按 rpc 分发) 对局推送 平台 → Game_Modify.Reconnect(info) → 重连处理(据数据重画) 重连 ``` 红线:**受限文件里只做“接住并转交”,业务逻辑写在新架构的 controllers/handlers 里**,不要在 `Game_Modify.*` 里堆逻辑。 --- ## 4. 加载顺序(index.html) `index.html` 按严格顺序加载脚本,**顺序即依赖**。典型分段: ``` 阶段0 引擎与 Spine vendor/gameabc.min.js → generated/spine_* → spine/SpineMgr.js 阶段1 框架核心 + 常量 gameabc-framework/core·system → 子游戏共享常量 阶段1.5 子游戏事件常量 追加到 EventBus.Events 阶段2 工具/数据结构/算法 子游戏共享算法 阶段3 精灵/资源/布局常量 整合入口最后加载 阶段4 框架 UI + 业务视图 gameabc-framework/ui/* → 子游戏视图组件 阶段5 控制器/管理器/网络 子游戏消息处理/资源管理/收发包 阶段6 旧受限对接层 01_SubGame/00_/01_/02_SubGame_*.js ``` > 上表按“职责”分段,非规定 `codes/` 的目录布局;具体目录/文件由子游戏自定,只要**被依赖者先加载**即可。 加载顺序的两条铁律: 1. **被依赖者先加载**。例如框架 `EventBus.js` 必须在子游戏事件常量之前、事件常量又必须在任何注册这些事件的视图之前;整合所有精灵常量的入口文件必须**最后**加载。 2. **新增文件要插对位置**。新增一个常量/组件文件,必须在 `index.html` 里插到其依赖之后、使用者之前,否则运行时拿到 `undefined`。 --- ## 5. codes/ 内部组织 `codes/` 是子游戏的自由开发区,**目录如何划分、文件如何命名,由子游戏自行决定**,本套文档不作强制规定。 只需把握两条通用原则(不依赖具体目录布局): - **职责分离、调用不重造**:一个职能只在一处实现,其他地方调用它,不复制近似逻辑(渲染/动画/音频/收发包/共享算法等,见 05「模块职责边界」)。 - **`shared/` 是唯一受约束的子目录**:它是服务端共享算法的同步副本,前端**只读**,改服务端权威源再同步(见 05「shared 同步」)。 --- ## 6. 小结 - 前端是浏览器静态资源 + gameabc 引擎,**严格 ES5**,跨文件按全局名引用、`index.html` 顺序加载。 - 三层:平台(禁改) / 框架(游戏中立、可复用) / 子游戏(单向依赖框架)。 - 新旧架构并存:平台事件经旧 `Game_Modify.*` 入口**转交**到新架构 handler;受限文件只接不写。 - 加载顺序即依赖,新增文件务必插对位置。 下一篇 [02-渲染与UI组件体系](./02-渲染与UI组件体系.md) 讲:精灵怎么画、资源常量怎么组织、UI 组件怎么写。