命名空间在运行时加载的顺序与用户代码中命名空间的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']);
* 运行编译后的代码会产生的控制台输出与{{out/cljs_deps.js}}中反映的顺序相同
e的内容
c的内容
g的内容
b的内容
d的内容
f的内容
分析
看起来在编译时确保顺序的一些工作已经包含在[CLJS-1453](
https://dev.clojure.org/jira/browse/CLJS-1453), 但在 {{cljs_deps.js}} 被生成之前,顺序可能已经混乱。
{{cljs_deps.js}}中给定ClojureScript文件的输出最终由{{cljs.compiler/emit-source}}的输出决定。那里的代码以与CLJS-1453之前{{cljs.analyzer}}中'ns'解析方法相同的方式移除重复的依赖。
所附修补程序解决了我的狭窄用例的问题,但我认为底层的函数正在作为映射传递`:uses`和`:requires`,因此可能需要更多工作才能得到完整的解决方案。