问题描述
我想创建一个 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
:它只会在代码被 deref
ed 后才执行。
你处理的“资源绑定”越多,就越有系统性 方法将为您的应用程序提供更好的结构。例如。看看:
那么为什么在 def
中放置阻塞的东西或副作用有问题?
Clojure 编译器的工作方式是实际“运行”代码。所以 compile
基本上是:
- 启用生成字节码并将其写为 .class 文件
- 加载命名空间并“运行”它
这意味着,在编译时,会执行顶级副作用。
因此,在 def
中阻塞操作,将阻塞编译(这是相当
很明显),否则你的 CI 服务器将无法编译,因为它无法连接到
数据库等
对 Clojure 中代码生成如何工作的一个很好的解释: