2024 年 Clojure 状态调查! 分享您的想法。

欢迎!有关此工作方式的更多信息,请参阅 关于 页面。

0
ClojureScript

调查 cljs.spec 对 :高级构建的影响。

目前所有规范都保存在(私有的)cljs.spec/registry-ref 原子中。此原子不被 Closure 编译器理解,并且不能被消除为死代码。因此,即使规范在“生产”中未使用,它们仍然会增加生成的 JS 的大小。有些规范可能在运行时使用,不能删除,而生成部分在 :高级构建中可能永远不会需要,并且应该以某种方式省略。

在一个测试构建(使用 1.9.93)中,一旦在使用了 cljs.spec,就会额外增加 11kb(102kb 对 91kb),并且随着每个定义的规范的增加而增加。

11 个答案

0

评论由:orestis 发布

在当前 CLJS 版本(1.10.439)中,我观察到几个 spec 导致了 60kb 的(优化后的)javascript —— 我只是在定义 spec 和 fdef,从不需要来自 spec 中的 s/valid? 或类似调用。这些数字来源于 shadow-cljs 报告。

cljs/spec/alpha.cljs 35.84 KB
cljs/spec/gen/alpha.cljs 27.33 KB

0

评论由:dnolen 发布

我将指出,这个问题似乎与多方法非常相似。鉴于规范是一个非常动态的功能,我对解决这个问题持有怀疑态度。

0

评论由:greybird 发布

我理解你对多方法(使用全局注册表)的看法,但根据我的想法,如果设置了 compile-asserts 为 false,且不使用 s/valid,那么他们应该可以完全通过构建过程中被移除。
(或类似设置)

0

评论由:dnolen 发布

Mark,《code>compile-asserts 仅应用于实际的 assert 使用。所以这与规范无关,可能性也不大。

0

评论由:greybird 发布

可能需要添加一个新的变量(如 compile-specs?),以防止规范被添加到注册表中。

我认为我无法在 CLJS 中使用规范,除非有方法在生产构建中移除它们,因为这对于尺寸非常敏感的移动应用来说会增加代码的大小。当然,并非所有人都处于这种状况,但在此情况下使用规范对于测试和开发时间调试将非常有益。

0

评论者:thheller

如果需要,规范很容易完全移除,问题是如果想要保留一些,就必须保留所有,因为我们无法在编译时判断将会使用什么。

因此,我同意我们可能无法在这方面做得更多。尽管如此,我们可能还可以减少生成的代码量。考虑到其中的一些代码在运行时立即构建并丢弃。例如,{{cljs.spec.alpha/def-impl}} 通过宏代码传递 3 个参数。其中一个是第二个参数 {{spec}} 的原始代码 {{form}}。对于大量的规范来说,{{form}} 参数将立即丢弃并且从未使用,因为第二个 {{spec}} 参数已经取代了它。闭包永远不会删除 {{form}},所以我们可能在宏上做得更聪明一些。

0

评论由:greybird 发布

使用新变量或编译器选项完全移除规范将满足我的需求。

我发现很难通过將它们放在单独的命名空间中和对开发构建进行配置来从生产构建中删除规范,而且我未能完全通过这种方式消除它们。我怀疑其他人也会觉得这样做很难。此外,对于规范及其函数之间保持大距离来说,对我来说并不理想。我更愿意将它们并排放置。

目前我只坚持使用 assert。

0

评论者:thheller

Closure Compiler 提供了一些选项,可以通过名称或前缀/后缀从构建中删除代码(链接:1)。我最近将其添加到 shadow-cljs 中(链接:2)。这允许通过以下方式通过暴力删除一切 spec:

:strip-type-prefixes #{"cljs.spec"}

它只能完全删除,但如果您需要这样做,它是相当合理的。可能应该单独创建一个工单来移植这些选项。

(链接:1) https://shadow-cljs.github.io/docs/UsersGuide.html#_code_stripping
(链接:2) https://github.com/thheller/shadow-cljs/blob/69316cfd0e041ef064696479cd33a65cfd4167d2/src/main/shadow/build/closure.clj#L165-L175

0

评论由:greybird 发布

感谢 Thomas。了解这些剥离选项很好,我现在正在使用 Shadow。

0

评论者:thheller

请注意,Closure 不喜欢某些模式,并且目前无法完全剥离 {{cljs.spec}}。它对 {{cljs.pprint}} 等东西工作得很好,但它与由 {{defonce}} 生成的代码有问题,因此可能需要调整。

0
参考: https://clojure.atlassian.net/browse/CLJS-1701(thheller 报告)
...