lein uberjar 永远 摆脱困境的方法那么为什么在 def 中放置阻塞的东西或副作用有问题?

问题描述

我想创建一个 leiningen 应用程序的 uberjar。我的配置是:

:uberjar {:omit-source true
             :aot :all
             :uberjar-name "myapp.jar"
             :source-paths ["env/prod/clj" ]
             :resource-paths ["env/prod/resources"]}

但是在执行lein uberjar时,我发现项目中的文件正在编译,但编译卡在包含大部分代码文件上,十分钟并计数。此文件不超过 140 行。

解决方法

TL;DR:从不def 副作用


如评论中所述:

...我只是想这行:(defonce server (http/start-server server-handler {:port 8982})) 导致挂起。

不要把这样的东西放在顶层。

defonce 只意味着它一旦在那里就不会被重新定义(所以在这种情况下 它会防止重新加载时出现一些“端口已在使用中”错误。

摆脱困境的方法

编写一个函数,启动这个服务器。然后从你的主要调用它。为了 开发你可以从 REPL 运行该函数,或者你可以撒一些 在您的 user-ns 中重新加载/重启逻辑。

另一种选择是使用 delay:它只会在代码被 derefed 后才执行。

你处理的“资源绑定”越多,就越有系统性 方法将为您的应用程序提供更好的结构。例如。看看:

那么为什么在 def 中放置阻塞的东西或副作用有问题?

Clojure 编译器的工作方式是实际“运行”代码。所以 compile 基本上是:

  1. 启用生成字节码并将其写为 .class 文件
  2. 加载命名空间并“运行”它

这意味着,在编译时,会执行顶级副作用。 因此,在 def 中阻塞操作,将阻塞编译(这是相当 很明显),否则你的 CI 服务器将无法编译,因为它无法连接到 数据库等

对 Clojure 中代码生成如何工作的一个很好的解释: