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

欢迎!请参阅 关于 页面以了解更多关于如何使用本网站的信息。

0 投票
ClojureScript

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

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

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

11 答案

0 投票

评论者:orestin

在当前的 CLJS 版本(1.10.439)中,我发现只有几个规范就有 60kb 的 (优化后的)javascript —— 我仅仅定义了规范和 fdefs,在生产代码中从未使用过任何源自规范的有效性检查或类似调用。这些数据来自 shadow-cljs 的报告。

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

0 投票

评论者:dnolen

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

0 投票

评论者:greybird

我明白你关于多方法(全局注册表的使用)的意思,但据我所知,如果未使用 compile-asserts,通过规范(specs)它们可以完全在构建过程中移除。
(或类似的选项)设置为 false。

0 投票

评论者:dnolen

Mark,compile-asserts 只适用于实际的 assert 使用。所以与规格无关,可能也不太可能相关。

0 投票

评论者:greybird

也许可以添加一个新的变量(compile-specs?),以防止规格被添加到注册表中。

在我看来,如果没有一种在产品构建中移除规格的方法,我就不能在没有移动应用程序的大尺寸代码增长的情况下使用规格,因为移动应用程序对尺寸非常敏感。当然,并非每个人都会处在这种情况,但在这个情况下使用规格对于测试和开发时间调试非常有用。

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。很高兴了解到strip选项,我目前正在使用Shadow。

0 投票

评论者:thheller

请注意,Closure不喜欢某些模式,并且无法目前完全删除{{cljs.spec}}。对于像{{cljs.pprint}}这样的东西效果很好,但是对于由{{defonce}}生成的代码则有问题,所以可能需要进行调整。

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