请在 2024 Clojure 状态调查! 中分享您的观点。

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

0
ClojureScript

研究 cljs.spec 对 :advanced builds 的影响。

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

在测试构建(带有 1.9.93)中,只要将 cljs.spec :require 到某个地方,就会增加 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 发表的评论:

我理解你关于多方法(全局注册表的使用)的看法,但考虑到spec,我认为如果将compile-asserts设置为false,并且不同时使用s/valid,它们可以被完全移除。
(或者类似的方法)。

0

由 dnolen 发表的评论:

马克,compile-asserts只适用于真实的assert用法。因此它与spec无关,可能也不会有。

0

由 greybird 发表的评论:

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

在我看来,如果没有一种方法在生产构建中移除它们,我就不能在CLJS中使用spec,因为对于非常关注大小的移动应用程序来说,代码大小的增加是一个问题。当然,并非所有人都会有这种情况,但在这个情况下使用spec对测试和开发时的调试非常有好处。

0

评论者:thheller

如果需要,spec可以很容易地完全删除,问题在于如果你想要保留一些,你必须保留所有,因为我们不能在编译时知道会用到什么。

所以我同意我们可能无法在这方面做什么。我们可以尽量减少生成的代码量。考虑到其中一些是在运行时构建并立即丢弃的。例如,宏代码通过{{cljs.spec.alpha/def-impl}}传递了3个参数。其中一个参数是第二个参数{{spec}}的实际代码{{form}}。对于大量spec,{{form}}参数将立即被丢弃且从未使用,因为第二个参数{{spec}}取代了它。但是Closure永远不会删除它,所以我们可以在宏中更智能一点。

0

由 greybird 发表的评论:

使用新的变量或者编译器选项来完全删除spec以满足我的需求。

我发现很难通过将它们放入单独的命名空间并调整开发构建来从生产构建中删除spec,而且我无法完全以这种方式摆脱它们。我怀疑其他人也会觉得很难。此外,对我而言,我希望spec与其函数之间有一定的距离并不可行,我更愿意将它们并排放置。

目前我仍然坚持使用断言(assert)。

0

评论者:thheller

Closure 编译器提供了一些选项,可以通过名称或前缀/后缀删除构建过程中的代码(链接: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 报告)
...