在运行时加载名称空间的顺序与用户代码中要求名称空间的顺序无关。这似乎影响所有优化级别。这意味着开发者不能依赖于在给定名称空间中首先运行具有副作用代码,然后再加载依赖于该副作用的另一个名称空间。
复现步骤
执行以下命令
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](
似乎给定ClojureScript文件的{{cljs_deps.js}}输出最终由{{cljs.compiler/emit-source}}的输出决定。那里的代码以与CLJS-1453之前在{{cljs.analyzer}}中使用的'ns'解析方法相同的方式删除重复的依赖项。
附带的补丁解决了我的近期用途中的问题,但我相信底层函数将`:uses`和`:requires`作为映射传递,因此可能还需要更多工作才能得到完整的解决方案。