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)中,我观察到几个规范后的(优化后的)javascript 大小为 60kb -- 我只是在定义规范和 fdefs,从未在从我生产代码中调用任何 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,compile-asserts 只影响实际的 assert 使用。因此,与规范无关,可能也不太相关。

0

评论由:greybird

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

我的看法是,如果不能在生产构建中删除规范,我就不能在生产环境中使用规范,因为移动应用对代码大小非常敏感,这会导致代码大小的增加。当然,并非所有人都会处于这种状况,但在这种情况下使用规范对测试和开发调试时间非常有好处。

0

评论由:thheller

如果需要,可以轻松地将规范完全删除,问题在于如果想要保留一些规范,必须保留所有规范,因为我们无法在编译时判断哪些会被使用。

因此,我同意我们可能无法做太多关于这一点。我们可能可以通过减少生成的代码量来达到目的。考虑到其中一些代码在运行时会立即构建和丢弃。例如,{{cljs.spec.alpha/def-impl}} 通过宏代码传递 3 个参数。其中一个是第二个 {{spec}} 参数的 {{form}} 原始代码。对于大量的规范,{{form}} 参数将被立即丢弃,永远不会使用,因为第二个 {{spec}} 参数取代了它。关闭函数将永远不会删除 {{form}},因此我们可以在宏中更加聪明地处理它。

0

评论由:greybird

使用为该目的创建的新变量或编译器选项完全删除规范将满足我的需求。

我发现很难通过将规范放在单独的命名空间并调整开发构建来从生产构建中删除它们,而且我无法通过这种方法完全删除它们。我怀疑其他人也会觉得很难。此外,我并不希望规范与其功能之间有太大的距离,我更希望它们并排放置。

到目前为止,我只是坚持使用断言。

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

感谢托马斯。了解这些移除选项很好,我目前正在使用 Shadow。

0

评论由:thheller

注意,Closure 不喜欢某些模式,目前无法完全删除 {{cljs.spec}}。对于像 {{cljs.pprint}} 这样的东西它是可以工作的,但它与由 {{defonce}} 生成的代码有问题,所以可能需要调整。

0
参考资料:https://clojure.atlassian.net/browse/CLJS-1701 (由 thheller 提出)
...