一直以来,web.sdk.js都是通过以下方式加载快游戏的。
<script src="./web.sdk.js"></script>
<script src="./main.js" type="module"></script>在大部分的游戏中也是没有问题的,由于web.sdk.js中存在大量的异步加载逻辑,因此将main.js定义为模块,并在代码最前面补充加载等待是对游戏原代码侵入较小的一种方案,而且恰恰是模块,因此顶级 await 也就非常顺理成章了。
await window.qg.ready();直到遇到下面某款游戏的入口(代码片段)
await window.qg.ready();
window['qg'].setIsUnityGame(true);
const xgame = qg;
require("ral.js");初步一看,看似没啥毛病对吧,非常简单的一个代码片段,但问题就出在了那行平平无奇的const xgame = qg;,由于main.js是模块,自带作用域隔离,因此此时的作用域是模块内部作用域,并非全局作用域,然后加载ral.js时就出问题了,ral.js是访问不到xgame的,会直接报错导致游戏加载中断。
为了解决这个问题,那么就不能将游戏入口定义为模块,不定义为模块,就没法在顶级 await,而且还得同时兼顾执行上下文的问题,在众多动态执行JS代码的方案中,那么很明显就只有动态创建script标签加载是最合适的了。
那么没办法,就只能在web.sdk.js中初始化自身后动态加载main.js了,由于快游戏的入口是固定的,因此直接硬编码加载也是没得问题的,这里处理后,main.js也就不需要await window.qg.ready();了,游戏入口代码零侵入。
window.qg._ready = true;
await requireAsync("main.js");