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

欢迎!有关该工具的工作原理,请参阅 关于 页面获取更多信息。

0
工具命名空间

路径为 {{public/js/out/foo/bar.cljc}} 的 cljc 文件以及 ns 形式 {{(ns foo.bar)}} 将导致命名空间 {{foo.bar}} 被重新加载。

这会带来问题,因为 ClojureScript 编译器会将所有输入文件复制到 {{:output-dir}} 以用于源映射。最近,随着更多库开始使用 cljc,这开始在库在 Clojure 环境中使用时引发问题。Cljs 编译会导致库代码的重新加载,可能会重新定义协议等,从而破坏 Clojure 环境。

我认为 tools.namespace 忽略文件路径和命名空间不匹配的更改是有意义的。
另一个问题是,为什么依赖关系解析在这种情况下不工作:依赖于输出目录中 cljc 文件上协议的命名空间没有被重新加载。

19 答案

0

评论由:deraen 提出

这与http://dev.clojure.org/jira/browse/TNS-24 几乎相同,但在这个情况下,不一致命名的命名空间将被重新加载,因为在正确路径上有一个副本。

0

评论由:deraen 提出

随附带测试的修补程序。

{{find-sources-in-dir}} 是进行检查的最简单的地方,因为我们需要目录路径。

  • 可能会对直接使用 {{find-sources-in-dir}} 的人造成破坏吗?
  • 现在 {{find-sources-in-dir}} 和 {{file/files-and-deps}} 都需要读取 ns 形式。
0

评论由:deraen 提出

在补丁中修复了一个错别字。

0

评论者:severeoverfl0w

我也遇到了这个bug。当它与双向结合使用时尤其糟糕,因为它使用了协议和记录。这个补丁完美地解决了我的问题。

0

评论者:stuart.sierra

这个问题的根本原因是在 {{resources/public}} 将编译好的“Web资源”如编译好的ClojureScript代码放在Java类路径上的常见做法。

现在有两种简单的解决方案可供选择

  1. 配置ClojureScript,将其编译文件放在不在类路径上的目录中
  2. 使用(链接:http://clojure.github.io/tools.namespace/#clojure.tools.namespace.repl/set-refresh-dirs 文本:set-refresh-dirs)从 tools.namespace 搜索中排除这些目录。

任何改变 tools.namespace 行为的事情,尤其是在低级API中,都有可能破坏其他用例,因此必须仔细考虑。例如,代码检查器可能使用 {{find-sources-in-dir}} 来搜索所有Clojure源文件,包括具有无效 {{ns}} 声明的文件。

0

评论由:deraen 提出

  1. 配置ClojureScript,将其编译文件放在不在类路径上的目录中

使用类路径来服务文件是最常见的方式,并且不太可能改变。很多工具,如Boot,鼓励使用类路径来服务文件。

  1. 使用set-refresh-dirs从tools.namespace搜索中排除这些目录。

在Boot上这不可能。在Boot中,类路径是由Boot管理的,一个目录将包含来自多个源的数据,例如Boot-cljs和{{source-paths}}。

0

评论者:severeoverfl0w

如果do-refresh在它的地图中接受一个sane-paths-only?选项,并且将其传递给它的调用到find/find-sources-in-dir,你愿意接受这个补丁吗?其中find-sources-in-dir接受一个可选的第三个参数,指定是否sane-paths-only?

find-sources-in-dir的最后一个参数重构为选项映射将会很方便,但打破该API可能超出了范围。

简而言之,如果仅在repl/refresh时运行,并通过参数传递,你会接受这个补丁吗?

0

评论者:malcolmjuxt

我同意你不应该在classpath中编译构件。

然而,由于uberjars,这在Clojure世界中是一种极其普遍的实践。

就我个人而言,我不喜欢uberjars,但似乎我是少数派!只要人们在生产中使用uberjars,他们就会希望在开发中从classpath中提供服务。

因此,我认为Stuart提出的两个简单解决方案都无法令人满意。

这是一个非常讨厌的bug,尤其是对于使用cljc库(例如bidi)的人。如果能提出另一个解决方案,那就太好了。

0

评论者:severeoverfl0w

  1. 使用set-refresh-dirs从tools.namespace搜索中排除这些目录。

我还注意到的这个策略的另一个问题是没有处理具有不同:source-paths的Leiningen配置文件。每次切换配置文件时,你必须修改对set-refresh-dirs的调用(并且当出错时会感到困惑)。

0

评论者:stuart.sierra

tools.namespace本不是为了在部署的应用中使用,因此我认为现在可以安全地忽略(链接:https://dev.clojure.org/jira/browse/TNS-45?focusedCommentId=44822&page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel#comment-44822 文本:uberjars)的情况。

如果意外路径中的文件被静默跳过,就难以理解为什么一个错名的文件没有加载。作为一个可能的妥协方案,{{c.t.n.find}}在遇到<{{ns}}>声明与路径不匹配的文件时,可以向* }打印一个警告,并从搜索结果中排除它。

这留下了一个虚假错误消息的问题。如上所述的评论中提到,(链接:https://dev.clojure.org/jira/browse/TNS-45?focusedCommentId=45080&page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel#comment-45080 文本:Leiningen配置文件)和(链接:https://dev.clojure.org/jira/browse/TNS-45?focusedCommentId=44149&page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel#comment-44149 文本:Boot)使得静态定义要扫描的目录集合变得困难。如果我们能够指定要搜索排除的目录,这够解决这个问题,即ClojureScript将{{.cljc}}文件复制到资源目录的问题吗?

0
by

评论由:deraen 提出

我认为uberjars提到的原因是因为人们从classpath中提供服务文件,而不是因为人们部署应用程序时使用c.t.n。

被排除的目录将定义为什么方式的文件路径或classpath前缀?

在Boot期间,用户不能控制包含在classpath中的目录。相反,Boot创建了一些它控制并包含在classpath中的临时目录。来自多个来源(项目资源路径、Cljs工件等)的文件都会被复制到同一个临时目录中,因此基于这一点无法排除Cljs工件。

定义要忽略的classpath前缀可能适用于Boot。

0
by

评论者:stuart.sierra

根据classpath前缀进行排除可能可行,但可能会有点棘手。目前,{{t.n.s.dir}}在不知道这些目录是否位于classpath上时搜索任意的文件系统目录。然而,如果排除作为classpath相关目录路径表达,它们可以解析为实际的文件系统路径。

还有一种可能性,就是用文件散列值代替现在的文件时间戳来确定文件何时“更改”。这将防止仅因为ClojureScript编译器复制了它们就重新加载{{.cljc}}文件。另一方面,这将是一个更具显著性的更改,它将防止使用{{touch}}(或编辑器的重保存)强制文件重新加载。

0
by

评论者:stuart.sierra

新补丁TNS-42-3.patch将责任从c.t.n.find提升到了c.t.n.dir。这避免了c.t.n.find/find-sources-in-dir的任何中断,同时实现了对c.t.n.repl/refresh的预期行为。

这可能是一个足够的妥协,尽管我仍然有点担心不正确的文件名会被静默忽略,从而导致混淆。

0
by

评论者:severeoverfl0w

可以添加被丢弃的文件/命名空间到跟踪器中,以减轻混淆。刷新时,它将像现在一样以prn的形式警告这些文件。

如果某个时刻文件变得有效,需要从丢弃列表中删除这些文件。

我不确定这是否应该阻止TNS-45,但可能是有人可以跟进的事情。

0
已回答

评论者:stuart.sierra

新补丁文件 TNS-45-4.patch 会打印警告并添加被忽略的目录到跟踪器,遵循 Dominic Monroe 在以下链接中的建议:https://dev.clojure.org/jira/browse/TNS-45?focusedCommentId=47280&page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel#comment-47280 文本:评论

这仅适用于 {{c.t.n.dir/scan-dirs}},因此 tools.namespace 中其他对低级 API 的使用不应受到影响。

在首次发现不匹配于 {{scan-dirs}} 的文件时,将打印警告,并使用声明的 {{ns}} 名称和文件路径打印到 * 中。之后,将忽略整个目录,并在每次调用 {{scan-dirs}} 时打印通知。我希望这能在信息性消息和不必要的警告之间取得良好的平衡。

注意:之前的补丁文件 TNS-42-3.patch 被错误地命名,但总是旨在应用于 TNS-45。

...