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

欢迎!请参阅关于页面获取有关此操作的更多信息。

0
tools.namespace

路径为{{public/js/out/foo/bar.cljc}}的cljc文件与ns形式{{(ns foo.bar)}}一起使用会导致命名空间{{foo.bar}}被重新加载。

这存在问题,因为ClojureScript编译器会将所有输入文件复制到{{:output-dir}}以供source-map使用。最近,随着更多库开始使用cljc,这已经开始在某些情况下导致问题,其中库在Clojure环境中使用。Cljs编译会导致库代码的重新加载,这可能重新定义协议等,并破坏Clojure环境。

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

19 答案

0

评论由:deraen

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

0

评论由:deraen

提出了一个带有测试的补丁。

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

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

评论由:deraen

在补丁中修复了一个拼写错误。

0

评论者:severeoverfl0w

我也遇到了这个错误。当与双向语言一起使用时,由于使用了协议和记录,这尤其糟糕。这个补丁完全解决了我的问题。

0

评论者:stuart.sierra

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

目前有两种简单的解决方案可用

  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

如果《code>do-refresh在其映射的《code>sane-paths-only?中接受了一个选项,并通过其调用传递到《code>find/find-sources-in-dir,您是否接受这个补丁?其中《code>find-sources-in-dir接受一个可选的第三个参数,指定是否使用《code>sane-paths-only??

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

简单来说,如果您接受这个补丁,那么《code>sane-paths-only?只会在repl/refresh时运行,并通过参数传递下来吗?

0

由malcolmjuxt发表的评论:

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

然而,这在大 Clojure 界非常普遍,因为uberjars的存在。

就我个人而言,我不喜欢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从未打算用于已部署的应用程序,因此在我看来,现在忽略(link: 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

评论由:deraen

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

排除的目录将以文件路径还是classpath前缀定义?

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

定义要忽略的classpath前缀可能会与Boot一起工作。

0

评论者:stuart.sierra

通过classpath前缀进行排除可能是可能的,但有些棘手。目前,{{t.n.s.dir}}在不知道那些目录是否在classpath上的情况下搜索任意文件系统目录。但是,如果排除是以classpath相对目录路径表示,它们可以被解析为实际的文件系统路径。

还有一种可能是,使用文件哈希值,而不是像现在这样使用时间戳来确定文件何时“更改”。这将防止仅仅因为ClojureScript编译器复制了它们就重新加载{{.cljc}}文件。另一方面,这将是一个更大的变化,并且它将防止使用{{touch}}(或编辑器中的重新保存)强制重新加载文件。

0

评论者: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

评论者: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。

...