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

欢迎!请在关于页面查看更多关于如何使用本站的信息。

0
ClojureScript

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

目前,所有规范都保存在(私有的)cljs.spec/registry-ref 原子中。该原子不被 Closure 编译器理解,不能作为死代码移除。因此,即使规范在“生产”环境中没有被使用,它们仍然会使生成的 JS 文件大小增加。一些规范可能在运行时使用,但不能被移除,但生成的部分可能永远不会在 :advanced 构建中使用,应予以省略。

在一个测试构建中(使用 1.9.93),只要在某个地方 require'd cljs.spec,就会增加 11kb(从 102kb 到 91kb),并且每个定义的规范都会使这个数字上升。

11 个答案

0

评论者:orestis

在当前 CLJS 版本(1.10.439)中,我观察到使用一些规范时(优化的)javascript 大小为 60kb -- 我只是在定义规范 & fdefs, never 使用来自 spec 的任何类似 s/valid? 的调用我的生产代码。我是从 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

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

我认为,在没有在生产构建中移除它们的方法的情况下,我无法在CLJS中使用规格,这是因为移动应用对代码尺寸非常敏感,规格会增加代码的大小。当然,并不是所有人都处于这种情况,但在这种情况下,使用规格对于测试和调试开发时间将非常有帮助。

0

评论者:thheller

如果需要的话,规格可以很容易地完全删除,但问题在于如果你想保留一些,你必须保留所有,因为我们无法在编译时确定会使用哪些规格。

因此,我同意我们可能无法在这方面做太多。然而,我们可能可以减少生成的代码量。考虑到其中一些是在运行时立即构建并丢弃的。例如,{{cljs.spec.alpha/def-impl}}通过宏代码传递三个参数。其中一个参数是第二个参数{{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报告)
...