【问题标题】:How can I conditionally load functionality in a clojure web-app如何有条件地在 clojure web-app 中加载功能
【发布时间】:2015-06-09 16:20:39
【问题描述】:

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

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

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

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

【问题讨论】:

  • 查看Environ 以及添加dev 和uberjar 配置文件的选项。
  • 谢谢 - 我已经在使用 environ 进行配置管理,所以 noisesmith 的回答很容易实现。

标签: clojure ring uberjar


【解决方案1】:

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

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

; 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 配置文件下的可选命名空间中的适当函数,否则为空操作。

【讨论】:

    猜你喜欢
    • 2014-02-12
    • 2014-05-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-03-10
    • 2019-01-27
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多