下载 App
一枚三角形撑起的十天:技术栈的妥协
2026-10-10
决定做《余烬荒原:群智回响》时,第一个问题不是玩法,是「怎么才能让别人双击就能玩」。
约束来自上一个项目。屏风镶嵌那套用的是 Vite + 原生 ES module,本地起服务一切正常,但把产物直接发给别人,双击 index.html 就是白屏 —— 浏览器对 file:// 下的 module 加载直接拦掉,控制台甩一行 CORS 报错,玩家看不懂,也不会去开什么本地服务器。
所以这一版的第一条硬规矩定得很早:不用框架、不用构建、不用 ES module。
具体落到三个决定:
- 13 个模块全部写成 IIFE,挂在 window.EW 命名空间上
- 入口页用 13 个 <script> 按依赖顺序加载
- 没有 import / export,跨模块调用一律 EW.xxx
代价是明摆着的:
- 改一个函数签名,得全项目搜索
- 没有 tree-shaking,13 个文件全量加载(444 KB,还能接受)
- 类型全靠命名规范和注释撑着
收益也很实在:
- 双击即玩,不需要 Node、不需要 npm、不需要任何环境
- 打包成 Electron 或 Android WebView 时几乎零适配
- 调试时改一行刷一下就行,没有 HMR 的心智负担
后来还发现一个副作用:本地静态服务不发缓存头,浏览器走启发式缓存,改了代码刷新还是旧的。于是加了 BUILD 号配上 ?b=NN 的缓存击穿。这个小设计后来救了很多次命 —— 每次「我明明改了啊」的错觉,最后查出来都是缓存。
第一天的画面很简陋:一个青色三角形、几个绿色圆点、一片黑。三角形是玩家,圆点是资源节点。没有美术资源,也不需要 —— 这个阶段要验证的只有「能不能动」。
这个技术栈选型最大的价值不是性能,也不是开发效率,是部署的确定性。整套代码从浏览器、Electron、WebView 到别人的机器上,运行环境永远是同一个 —— 一个 <canvas> 加一堆 <script>。没有构建产物和源码的差异,没有开发环境和生产环境的差异,出了问题只看一份文件。
代价是工程化能力的全面缺失:没有模块化、没有类型检查、没有热更新、没有代码分割。对十天的 Demo 来说这是划算的交易。






