如何在clojure web-app中有条件地加载功能

时间:2015-04-04 21:12:52

标签: clojure ring uberjar

我有一个clojure网络应用程序(标准环处理程序和jetty服务器上的组件路由),我为此启用了实时资产重新编译作为中间件,这在开发中非常方便。随着我们接近生产,我想找到一种方法,不在生产中加载该代码,而是读取预编译的资产(我能够生成lein任务)。

目前资产编译机器存在于项目代码中 - 它可以使用eval-in-project从lein任务加载,因此我可以在两个地方重用相同的代码。但是,这意味着编译了不需要的文件并将其包含在生产应用程序中。

另一个问题是我正在使用的一个资产编译工具导致应用程序无法在初始化时加载,如果uberjar'ed因为它使用了本机绑定到v8,这是不可用的(而不是当预编译资产可用时。

如何避免在生产uberjar中加载此代码,但仍然可以在开发和测试期间的运行时动态重新编译中获益?

1 个答案:

答案 0 :(得分:2)

Leiningen中的:source-paths键决定检查哪些目录是否为Clojure源代码。使用:source-paths的每个环境设置,您可以防止不需要的名称空间被包含在您的depoloyed uberjar中。

下一个难题是确保您的代码不依赖于生产实例上的开发代码。这可以在environ lib。

的帮助下完成
; excerpt of project.clj
(defproject your-org/your-project "version"
   :source-paths ["src"] ; the main source location
   :profiles {:dev {:source-paths ["dev-src"] ; added directory
                    :env {:dev "true"}}}
 ...)

; excerpt of project code for src/your_org/your_project.clj
(ns your-org.your-project
  (:require environ.core :refer [env]))

(def maybe-launch-optional-thing
  (if (= (env :dev) "true") ; checking a profile specific value
   (do (require 'dev-only-dep.core)
       (resolve 'dev-only-dep/launch))
   (constantly nil))

...

(defn -main
  [& args]  
  (maybe-launch-optional-thing)
  ...)

if包裹require以及resolve的使用,确保此代码无效dev-only-dep.core是否可用。 maybe-launch-optional-thing绑定到:dev配置文件下的可选命名空间中的相应函数,否则为无操作。