如何有条件地在Clojure Web应用程序中加载功能 [英] How can I conditionally load functionality in a clojure web-app

查看:110
本文介绍了如何有条件地在Clojure Web应用程序中加载功能的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个Clojure Web应用程序(码头服务器上的标准铃声处理程序和compojure路由),为此我启用了实时资产重新编译作为中间件的功能,这在开发中非常方便.当我们接近生产时,我想找到一种方法,不在生产中加载该代码,而是读取预编译的资产(我可以将其作为lein任务生成).

I have a clojure web app (standard ring handlers and compojure routes on a jetty server) for which I enabled live asset recompilation as middleware, which has been very very handy in development. As we get closer to production I would like to find a way not to load that code in production and instead read the pre-compiled assets (which I am able to generate as a lein task).

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

Currently the asset compilation machinery lives in the project code - it can be loaded from the lein task using eval-in-project, so I am able to reuse the same code in both places. However this means that the un-needed files are compiled and included in the production app.

另一个问题是,我使用的是一个资产编译工具,如果使用uberjar,则会导致应用在初始化时无法加载,因为它利用了与v8的本机绑定(并且不可用) (如果需要)预编译资产可用.

The other issue is that there is one asset compilation tool I'm using that causes the app to fail to load at initialisation time if uberjar'ed since it makes use of native bindings to v8, which are not available (and not needed) when the precompiled assets are available.

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

How can I avoid loading this code in a production uberjar, but still benefit from dynamic re-compilation at run-time during development and testing?

推荐答案

您在Leiningen中的:source-paths键决定检查Clojure源代码的目录.通过将每个环境设置为:source-paths,可以防止将不需要的名称空间包含在已部署的uberjar中.

Your :source-paths key in Leiningen decides which directories are checked for Clojure source code. With per-environment settings of :source-paths you can prevent unwanted namespaces from being included in your depoloyed uberjar.

下一个难题是确保您的代码不依赖生产实例上的dev代码.可以在 environ lib的帮助下完成.

The next piece of the puzzle is to ensure your code does not rely on the dev code on the production instance. This can be done with the help of the 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包装的requireresolve的用法,确保无论dev-only-dep.core是否可用,此代码均有效. maybe-launch-optional-thing绑定到:dev配置文件下可选名称空间中的适当功能,否则为空操作.

The if wrapped require, and the usage of resolve, ensure that this code is valid whether dev-only-dep.core is an available or not. maybe-launch-optional-thing is bound to the appropriate function in the optional namespace under a :dev profile, and is otherwise a no-op.

这篇关于如何有条件地在Clojure Web应用程序中加载功能的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆