我正在考虑将一个项目从启动转移到Gradle,clojurephant希望更多地利用Gradle生态系统。该项目构建了一个大型uberjar,其中包含一个带有Ring和Jetty的Clojure项目,该项目又提供了一个使用re-frame构建的ClojureScript应用程序。
在引导中,我基本上只需要引导cljs,添加了
(boot-cljs/cljs :optimizations :advanced)
到我的构建任务,它还调用(pom)
、(aot)
和(uber)
(所有标准引导任务(,一切都很顺利。
使用Clojurephant,我发现Clojure和ClojureScript部分最终位于不同的子目录中。特别是在build
下面
clojure/main
clojurescript/main
resources/main
(本质上是我的resources
项目文件夹的副本(
更让我困惑的是,这些路径并没有以我可以看到的方式转换为Gradle使用影子插件构建的Uberjar的结构
我的build.gradle
:摘录
plugins {
id 'dev.clojurephant.clojure' version '0.5.0'
id 'dev.clojurephant.clojurescript' version '0.5.0'
id 'application'
id 'com.github.johnrengelman.shadow' version '5.0.0'
id 'maven-publish'
id 'distribution'
id 'com.meiuwa.gradle.sass' version '2.0.0'
}
// ...
clojure {
builds {
main {
aotAll()
}
}
}
// ...
clojurescript {
builds {
all {
compiler {
outputTo = 'public/app.js'
outputDir = 'public/js/out'
main = 'com.example.mycljsstuff'
assetPath = 'js/out'
}
}
main {
compiler {
optimizations = 'advanced'
sourceMap = 'public/app.js.map'
}
}
dev {
compiler {
optimizations = 'none'
preloads = ['com.example.mycljsstuff']
}
}
}
}
编辑:忘了提一下,在引导时,我配置init函数来开始在一个名为app.cljs.edn
的文件中加载CLJS代码。使用Clojurephant,我只找到了一种设置主名称空间的方法,而不是一个函数。
我的问题最终是,如何配置ClojureScript构建,使其在从Uberjar交付时最终能够工作?
Clojure的事情似乎奏效了。Ring和Jetty愉快地运行并交付了第一个静态网页。但是所有的CLJS/JS东西都找不到。
如果能收到一些我可以学习的其他项目、文档或教程的指针,我会非常高兴。我没有发现太多,然后在理解Clojurephant本身的代码时迷失了方向。
一年前,在工作中,我能够拆分一个组合的CLJ&CLJS(backend/frontend(项目分为两个独立的项目:纯Clojure用于后端,纯ClojureScript用于前端。这解决了我们遇到的很多问题,我再也不会试图在同一个项目中保留两个代码库了。
- 后端CLJ部分继续使用Lein作为构建工具。这并不完美,但大家都很清楚
- 前端CLJS部分从最初的Figwheel(又名"1.0"(过渡到新的Figweel Main(又名"2.0"(我们选择使用Deps/CLI(最初的组合项目将Lein用于所有内容(来重组构建。从Lein过渡到Deps/CLI是CLJS工作的真正赢家
虽然Deps/CLI非常适合纯Clojure代码,但请注意,它本身并不支持包含Java源代码。我有一个模板项目您可以克隆,它显示了一个简单的解决方法。
对于任何CLJS项目,我强烈建议使用Figfheel Main而不是原来的Figfheer,因为它是一种主要的"2.0"类型的升级,会让你的生活变得更好。
享受吧!
试图在这里回答我自己的问题,因为我设法让它运行起来了。
Clojure
plugins {
id 'dev.clojurephant.clojure' version '0.5.0'
id 'application'
id 'com.github.johnrengelman.shadow' version '5.0.0'
// ... more to come further down
}
group = 'com.example'
version = '1.0.0-SNAPSHOT'
targetCompatibility = 1.8
mainClassName = 'com.example.myproject'
dependencies {
implementation(
'org.clojure:clojure:1.10.1',
'ring:ring:1.8.0',
// and many more
)
testImplementation(
'junit:junit:4.12',
'clj-http-fake:clj-http-fake:1.0.3',
'ring:ring-mock:0.4.0'
)
devImplementation(
'org.clojure:tools.namespace:0.3.0-alpha4',
'cider:cider-nrepl:0.21.1',
'org.clojure:java.classpath',
'jonase:eastwood:0.3.11',
'lein-bikeshed:lein-bikeshed:0.5.2'
)
}
clojure {
builds {
main {
aotAll()
}
}
}
clojureRepl {
handler = 'cider.nrepl/cider-nrepl-handler'
}
当从命令行调用./gradlew shadowJar
时,这足以从com.example.myproject
命名空间获得运行-main
的可执行JAR。不确定application
插件是否与此处相关。此外,./gradlew clojureRepl
启动一个可以连接Emacs/Cider的nrepl。
ClojureScript
// Merge with plugins above. Reproduced only the CLJS relevant
// part here
plugins {
id 'dev.clojurephant.clojurescript' version '0.5.0'
}
// Again, merge with dependencies above
dependencies {
implementation(
// ....
'org.clojure:clojurescript:1.10.597',
're-frame:re-frame:0.10.5',
'reagent:reagent:0.7.0',
// and a few more
)
}
clojurescript {
builds {
all {
compiler {
outputTo = 'public/app.js'
outputDir = 'public/state/'
main = 'com.example.myproject.webui'
assetPath = 'status/app.out'
}
}
main {
compiler {
optimizations = 'advanced'
sourceMap = 'public/app.js.map'
}
}
dev {
compiler {
optimizations = 'none'
preloads = ['com.example.myproject.webui']
}
}
}
}
这在JAR的顶层创建了一个/public
文件夹,在该文件夹中创建了app.js
,这就是Ring交付的HTML文件所期望的位置
对我来说,一个重要的步骤是在CLJS文件中调用我的init
CLJS函数,该函数以前由其他组件负责。我不确定这个设置是否完全正确,最终是否会进行figwheel设置。也许那时就不需要呼叫init
了。
CSS
// Merge ....
plugins {
id 'com.meiuwa.gradle.sass' version '2.0.0'
}
sassCompile {
output = file("$buildDir/resources/main/public/")
source = fileTree("${rootDir}/src/main/resources/public/")
include("**/*.scss")
exclude("**/_*.sass", "**/_*.scss")
}
这会在正确的位置将我的app.scss
编译为app.css
,我的HTML文件会在那里搜索它
Pro&Con
迁移后,我获得免费
- 正确设置缓存后,本地和CI中的编译速度更快
- 使用插件
com.github.jk1.dependency-license-report
和org.owasp.dependencycheck
进行许可证和OWASP dep检查报告,插件的等效项存在于leiningen中,但不在引导(AFAIK(中 - Maven发布通过HTTP头进行身份验证,而不是启动时不可用的用户名/密码
缺点:
- 我的构建文件中的语法很糟糕。不,真的
- 我必须手动在Emacs中输入nrepl端口号