且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

构建和部署Clojure应用程序的***实践:好的教程?

更新时间:2023-09-13 20:27:52

一些快速提示,然后是一些链接:

A couple of quick hints, then some links:

在开发期间不使用 lein uberjar 喜欢 lein jar 。区别是 lein uberjar 将所有的依赖关系放在生成的 jar (包括Clojure本身)中, jar是一个完全自包含的包里面有你的应用程序; lein jar 只能保存您自己的代码。 uberjar 方法对部署有明显的好处,但是对于开发,您应该能够在运行应用程序时只使用适当的类路径,从而节省准备uberjar所需的时间。如果您不想手动管理测试运行的类路径,请查看 lein run 插件

Don't use lein uberjar during development; prefer lein jar. The difference is that lein uberjar puts all your dependencies in the generated jar (including Clojure itself), so that your single jar is an entirely self contained package with your app inside; lein jar only jars your own code. The uberjar approach has obvious benefits for deployment, but for development, you should be able to just use the appropriate classpath when running your app, saving yourself the time necessary to prepare an uberjar. If you don't want to hand-manage the classpath for test runs, check out the lein run plugin.

此外,大多数代码实际上不应该被AOT编译。 AOT在某些Java互操作场景中是必需的,但大多数时候它会带来启动速度的轻微提升以及与不同版本的Clojure的二进制兼容性的恼人问题。我想后一个问题与一个 uberjar -ed独立应用程序类型的项目无关,但任何库代码至少应该被保留为JIT-ed如果可能的话。使用Leiningen,您可以在 project.clj中的 defproject 表单中插入:namespaces 以确定要编译哪些命名空间;默认情况下,任何您遗漏的内容都将被JIT编辑。默认情况下,Leiningen的旧版本用于编译所有内容,这实际上是升级的好理由!

Also, most likely the majority of your code should not actually be AOT compiled. AOT is necessary in some Java interop scenarios, but most of the time it brings one a slight boost in startup speed and annoying problems with binary compatibility with different releases of Clojure. I suppose the latter issue is not relevant to an uberjar-ed standalone app kind of project, but any library code at least should be left to be JIT-ed if at all possible. With Leiningen, you can put a :namespaces clause in the defproject form in project.clj to determine which namespaces are to be compiled; whatever you leave out will currently be JIT-ed by default. Older versions of Leiningen used to compile everything by default, which is actually a good reason to upgrade!

至于在编译期间弹出的窗口,我猜你'在宏扩展时或在任何函数定义或类似构造之外运行窗口外弹出代码。 (像在顶层的一个(printlnFoo!))这只是你不应该做的,我想 - 除非你打算运行代码作为脚本,反正。为了避免这个问题,将副作用代码放在函数定义中,并使用 project.clj中的:main 。 (如果你说:main foo ,则 -main code>命名空间将被用作你的应用程序的入口点,这是默认的,反正至少上面提到的 lein run 似乎有硬编码的名称 - 不知道lein本身。)

As for the windows popping out during compilation, I would guess that you're either running window-out-popping code during macro expansion time or outside of any function definition or similar construct. (Something like a (println "Foo!") at the top level.) That's just something you shouldn't do, I suppose -- unless you are planning to run your code as a script, anyway. To avoid the problem, wrap side-effecting code up in function definitions and provide an entry point to your application using the :main clause in project.clj. (If you say :main foo, then the -main function from the foo namespace will be used as the entry point to your app. That's the default, anyway, and at least the above mentioned lein run seems to have the name hardcoded -- not sure about lein itself.)

对于重置REPL的状态 - 你可以重新启动它。有了SLIME,Mx slime-restart-inferior-lisp就能做到这一点,同时保持Emacs会话的所有其他状态。

As for resetting the state of the REPL -- you can just restart it. With SLIME, M-x slime-restart-inferior-lisp will do just that while maintaining all other state of your Emacs session.

另请参见Clojure Google组中的这些讨论:

See also these discussions on the Clojure Google group:


  1. Clojure for system administration

  2. 预填包装clojure(was:Re:Clojure for system administration)

  3. Leiningen,Clojure和libraries:我缺少什么?

  1. Clojure for system administration
  2. Prepping clojure for packaging (was: Re: Clojure for system administration)
  3. Leiningen, Clojure and libraries: what am I missing?