命名空间在运行时加载的顺序与在用户代码中{{require}}的顺序无关。这似乎会影响所有优化级别。这意味着开发人员不能依靠某个命名空间中的副作用代码在依赖于该副作用的其他命名空间加载之前运行。
重现步骤
运行以下命令
clj --main cljs.main --compile-opts '{:target :nodejs :main a}' --compile a
将编译{{a.cljs}}中定义的{{a}}命名空间。该命名空间通过{{ns}}宏的{{:require}}形式按字母顺序需要命名空间{{b}}到{{g}}。
编译后观察以下内容
* 输出{{out/cljs_deps.js}}文件中{{a.js}}的goog.addDependency调用包括其依赖项的任意顺序。例如,在我的机器上的一次运行结果为
goog.addDependency("../a.js", ['a'], ['cljs.core', 'e', 'c', 'g', 'b', 'd', 'f']);
* 运行编译后的代码的{{node out/main.js}}给出的控制台输出表明,运行时的加载顺序与{{out/cljs_deps.js}}中反映的顺序相同
e的主体
c的主体
g的主体
b的主体
d的主体
f的主体
分析
看起来确保编译时顺序的工作已作为[CLJS-1453](
https://dev.clojure.org/jira/browse/CLJS-1453)的一部分完成,但似乎在 CJLS-1453 之前,镀铬分析器中的'ns 解析方法之前,相同的依赖项会被消重。
似乎由特定ClojureScript文件产生的{{ cljs_deps.js }}的输出最终由{{ cljs.compiler/emit-source }}的输出决定。那里的代码以类似于CLJS-1453之前在{{ cljs.analyzer }}中的'ns 解析方法的方式去除重复的依赖项。
附加的补丁解决了我的特定用例的问题,但我相信底层函数是将`:uses`和`:requires`作为映射传递的,因此可能需要进行更多工作以实现完整的解决方案。