shadow-cljs是新一代的cljs打包工具,比起以前的cljsbuild和figwheel的优势主要是:
- 支持直接引用npm依赖, 以前还需要使用
cljsjs
转一次,不仅麻烦而且还是过时的
- 和webpack类似的代码分割, 依赖
当然,cljs+css代码重载是最基本的,而且构建速度也足够快
基于这些特点,打算采用shadow-cljs
来编译cljs
想法是好的,实际运行的发现现实总是骨感的…
1. 安装shadow-cljs
我先创建了一个luminus
的应用,然后按照shadow-cljs官网所说,直接安装跑起来
1
2
3
4
|
lein new luminus shadow-gen
cd shadow-gen
yarn add shadow-cljs
shadow-cljs init
|
2. shadow-cljs打包配置
然后我创建一个Build配置
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
|
;; shadow-cljs configuration
{:source-paths
["src/cljs" "env/dev/cljs/"]
:dependencies
[[org.clojure/clojurescript "1.9.946"]
[re-frame "0.10.5"]
[reagent "0.7.0"]
[secretary "1.2.3"]
[cljs-ajax "0.7.3"]
[day8.re-frame/re-frame-10x "0.2.0"]]
:verbose true
:builds
{:app {:target :browser
:output-dir "target/cljsbuild/public/js"
:asset-path "/js"
:dev
{:compiler-options {:closure-warnings {:global-this :off}
:closure-defines {"re_frame.trace.trace_enabled_QMARK_" true}
:source-map true
:optimizations :none
:pretty-print true}}
:release
{:compiler-options {:optimizations :advanced
:pretty-print false
:closure-warnings
{:externs-validation :off :non-standard-jsdoc :off}}}
:modules {:app {:entries [shadow-gen.app]}}
:devtools {:after-load shadow-gen.core/mount-components
:preloads [day8.re-frame-10x.preload]
}
}}
}
|
开了day8.re-frame-10x.preload
半天页面一直崩,问了下作者thheller发现reframe的dev工具有bug,现在还无解…
然后lein repl
,start之后,访问一下localhost:3000
, 一开始是好的,后来改下代码hmr之后发现果然崩了。。
打开app.cljs一看,由于figwheel-no-load
元数据, figwheel每次重载都会避开app.cljs,
1
2
3
4
5
6
7
8
9
|
(ns ^:figwheel-no-load shadow-gen.app
(:require [shadow-gen.core :as core]
[devtools.core :as devtools]))
;; shadow-gen自带了devtool不需要这些了
;; (enable-console-print!)
;; (devtools/install!)
(core/init!)
|
shadow-gen不会skip,每次都会reload整个ns,然后init!的时候会重复创建goog.History对象,就崩了,
跟作者提了下,作者当天就把这个功能加上去了。。。
后来请教了下赵宇少侠,发现把core.cljs里的init!导出,然后在html引的时候直接调用core里的init也是一种很好的解决方案,
然后把entry改成core.cljs,每次重载的时候调用edn里配置的:after-load
去mount就好了
1
2
3
4
5
6
|
{% script "/js/app.js" %}
<script type="text/javascript">
var context = "{{servlet-context}}";
var csrfToken = "{{csrf-token}}";
shadow_gen.core.init_BANG_(); // 加了这行
</script>
|
3. 整合leiningen
这样打包基本就ok了,怎么和lein这个呢,我的代码里既有java代码,又有clj和cljs代码
一开始我是先编译cljs的
shadow-cljs release app
然后发现leiningen在编译的时候,直接会清空target目录…
翻了下leiningen文档,发现在pretask里可以指定任务顺序,我的是先编译java,然后编译clj,最后使用shadow.cljs.devtools.cli
编译cljs
lein里面javac可以编译java,compile编译clj, 去掉原来的:cljsbuild
最后配置是这样
1
2
3
4
5
6
7
|
{:uberjar {:omit-source true
:main ^:skip-aot shadow-gen.core
:prep-tasks ["javac" "compile" ["run" "-m" "shadow.cljs.devtools.cli" "release" "app"]]
:aot :all
:uberjar-name "shadow-gen.jar"
:source-paths ["env/prod/clj"]
:resource-paths ["env/prod/resources"]}}
|
这样就大功告成了! 成功把shadow-cljs和leiningen整合,完美java,clj,cljs混编!