在运行时加载命名空间的顺序与用户代码中命名空间被require时的顺序无关。这似乎影响所有优化级别。这意味着开发人员不能依赖特定命名空间中具有副作用的有效代码在依赖该副作用的另一个命名空间被加载之前先执行。
重现步骤
运行命令:
clj --main cljs.main --compile-opts '{:target :nodejs :main a}' --compile a
将编译在{{a.cljs}}中定义的{{a}}命名空间。该命名空间通过ns宏中{{:require}}形式的{{ns}}需要按字母顺序命名空间{{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)中,确保编译时顺序所做的某些工作似乎已经完成,但似乎在{{cljs_deps.js}}被生成之前事情会变得混乱。
似乎给定ClojureScript文件的{{cljs_deps.js}}输出最终由{{cljs.compiler/emit-source}}的输出决定。那里的代码以类似于在CLJS-1453之前在{{cljs.analyzer}}中执行的'ns'解析方法的方式删除了相同的依赖项。
附带的补丁解决了我在狭窄用途中的问题,但我认为底层的函数正在以映射的形式传递`:uses`和`:requires`,因此可能需要更多工作才能找到完整解决方案。