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)中,我曾经观察到包含几个规范时的 60kb (优化的)javascript – 我只是在定义规范和 fdefs,从未在我的生产代码中使用过来自规范的任何 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}} 的 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 报告)
...