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

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

0 投票
ClojureScript

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

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

在测试构建中(1.9.93),只要某处使用了 cljs.spec,就会增加 11kb(从 102kb 增加到 91kb),每个定义的规范都会增加。

11 答案

0 投票

评论者:orestis

在当前 CLJS 版本(1.10.439)中,我观察到了包含几个规范(已优化)的 60kb 的 javascript – 我只是定义规范和 fdefs,在我的生产代码中从未使用过规范中的任何 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,就可以在构建过程中完全去除。
(或者类似的情况),当未使用 s/valid 时,将其设置为 false。

0 投票

评论者:dnolen

马克,《code-asserts》只适用于实际的 assert 使用。因此,与规范无关,可能也不太可能。

0 投票

评论者:greybird

也许可以添加一个新的变量(编译规范?),以防止规范被添加到注册表中。

我的观点是,在没有一种方法在产品构建中去除它们的情况下,我无法在 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)。这允许通过下面的方式通过暴力删除所有规范:

: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。很高兴了解关于strip选项的事情,我目前正在使用Shadow。

0 投票

评论人:thheller

需要注意的是,Closure不喜欢某些模式,并且目前无法完全删除{{cljs.spec}}。对于{{cljs.pprint}}之类的功能,它运行良好,但对于{{defonce}}生成的代码,则存在问题,因此可能需要进行调整。

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