(compile 'my.namespace) ;; writes .class files to *compile-path*
你知道吗
大多数库都以源代码形式发布,你需要反复编译它们
你可以使用 compile
显式编译命名空间
命名空间编译是可传递的
compile
会将这些文件写入磁盘,require
将使用它们
你可以使用 compile
编译你在开始开发时加载的命名空间,或者编译你的 user.clj
,或者编译你作为服务器运行的主要命名空间,从而提升启动时间
compile
函数接受一个命名空间符号,并将该命名空间及其所有依赖项编译到 *compile-path*
(默认值为 classes
)。该目录必须存在,并且必须在你的类路径中
(compile 'my.namespace) ;; writes .class files to *compile-path*
之后,当任何这些已编译的命名空间被要求时,将会加载类文件,而不是原始的 .clj
文件。如果源文件更新(因此更新),则会改为加载源文件。你需要定期重新编译,以应对新的依赖项或代码更改。
请注意,编译是加载的副作用,因此对已加载的命名空间没有影响。特别是一个特殊情况是 user.clj
文件,该文件由 Clojure 运行时自动加载。如果你在开发中使用 user.clj
(或需要编译已经编译的命名空间),你可以通过在编译时强制重新加载来做到这一点
(binding [*compile-files* true] ;; compile during load
(require 'user :reload-all)) ;; reload this and all transitively loaded namespaces
就是这样!这种技巧可以显着缩短开发过程中的启动时间,尤其是在加载的依赖项数量增加时。
在 deps.edn 项目中,你应该创建一个开发别名(例如 :dev
),其中包含 classes
目录
{:deps { ... }
:aliases
{:dev {:extra-paths ["classes"]}}}
你还需要确保 classes
目录存在。将空的 classes
目录作为版本控制项目结构的一部分可能很有用(确保忽略并不要包含已编译的 .class 文件)。
然后,你可以使用别名启动 REPL 并使用 compile
来填充 classes
目录,并开始看到好处
$ clj -A:dev
Clojure 1.10.1
user=> (compile 'my.namespace)
如果你想使用自动加载的 user.clj,你应该通过添加源路径 dev
来将其纳入你的开发别名
{:deps { ... }
:aliases
{:dev {:extra-paths ["dev" "classes"]}}}
然后创建 dev/user.clj
(ns user
(:require ... ))
;; dev-only functions, etc
记住对 user.clj 使用修改后的编译过程
$ clj -A:dev
Clojure 1.10.1
user=> (binding [*compile-files* true] (require 'user :reload-all))
原始作者:Alex Miller