请在2024年Clojure调查问卷!中分享您的想法。

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

0
ClojureScript

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

目前所有规范都保存在(私有的)cljs.spec/registry-ref原子上。该原子不被Closure Compiler理解,因此不能将其视为冗余代码删除。因此,即使规范在“生产”中未使用,它们仍然增加了生成的JS大小。有些规范可能在运行时使用,无法删除,但是在:advanced构建中,生成部分可能永远不会需要,因此应 somehow省略。

在一个测试构建(使用1.9.93)中,一旦在某个地方require cljs.spec,就会增加11kb(102kb对91kb),并且随着时间的推移,每个定义的规范都会增加。

11 答案

0

评论者:orestis

在当前CLJS版本(1.10.439)中,我观察到由于几个规范,有60kb的(优化过的)JavaScript。我只是定义了规范和fdefs,在我的生产代码中从未使用过来自规范的有效s/valid?或类似的call。我的数字来自shadow-cljs报告。

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

0

评论者:dnolen

我将指出,这个问题似乎与multimethods的问题非常相似。鉴于规范是一个非常动态的功能,我对解决这个问题的可能性表示怀疑。

0

评论者:greybird

我理解你关于多方法(使用全局注册表)的看法,但是根据规范,我原以为在编译时如果将 compile-asserts 设置为 false,就不会使用到 s/valid,这样它们可以被完全删除。
(或类似设置)时。

0

评论者:dnolen

马克,compile-asserts 仅适用于实际的 assert 使用。所以这与规范无关,也很可能不是。

0

评论者:greybird

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

我的观点是,在CLJS中我不可以使用规范,除非有一种方法在产品构建中删除它们,因为移动应用对代码大小非常敏感,这会导致代码大小的增加。当然,并非每个人都处于这种情况,但在这种情况下,使用规范将对测试和开发调试非常有用。

0

评论由:thheller 提出

如果需要,规范可以很容易地完全删除,但是问题在于如果想要保留一些,则必须全部保留,因为我们无法在编译时确定将使用哪些规范。

因此,我同意我们可能无法在这方面做太多事情。尽管如此,我们可能会减少生成的代码量。考虑到其中一些代码只是在运行时构建并立即丢弃。例如,宏代码通过宏传递了三个参数给 {{cljs.spec.alpha/def-impl}}。其中一个是要传递给第二个参数 {{spec}} 的原始代码 {{form}}。对于大量的规范,{{form}} 参数会被立即丢弃并且永远不会使用,因为第二个 {{spec}} 参数会取代它。封闭环境永远不会删除 {{form}},但在宏中我们可以更聪明地处理这一点。

0

评论者:greybird

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

我发现很难通过将它们放入单独的命名空间并欺骗开发构建来从产品构建中删除规范,而且我也没有以这种方式完全删除它们。我怀疑其他人也会觉得很难。此外,对于规范和其功能之间的大距离,对我来说根本不希望,我更愿意把它们并排放置。

目前我只是坚持使用 assert。

0

评论由:thheller 提出

Closure Compiler 具有一系列选项,可以通过名称、前缀或后缀来移除构建中的代码(链接:1)。我最近将其添加到 shadow-cljs 中(链接:2)。这允许通过以下方式 brute force 移除所有规范:

: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 报告)
...