shadow-cljsというツールが話題になっていたので触ってまとめてみた。
npm界隈を知らないので認識が違うこともあるかもしれない。
バージョンは0.18.7
を使用している。
目的
READMEによると以下の目的があって作られた物らしい
- ClojureScriptのデフォルトのビルドapiを親切な物で置換する
- ClojureScriptのビルドと既存のJavaScriptとのビルドツール間の連携を行いやすくする
特徴
- npm/yarnがあればインストールできる
- Javaがインストールされていない場合はnode-jreにフォールバックする
- node-jreはnpm/yarnでインストールすることができる
- Javaがインストールされていない場合はnode-jreにフォールバックする
- 1つビルドの設定から、開発用ビルド/リリースビルドのような異なるタスクが実行できる。
- ClojureScriptのAPIの場合、タスク毎にそれぞれ異なるビルドの設定が必要で冗長になりがち
- 単一のcliツールとして利用することができる
- Clojureのライブラリとして使うこともできる
機能
- ビルドができる
- npmモジュールとの密な連携
- npmモジュールを特別な設定無くnamespaceとして使える
- externも大体ケアされる
- figwheelのようにファイルの変更を検知→ホットローディングが可能
-
演出は無く、コンソール出力のみ-> shadow-cljsロゴが表示されるようになった
-
- cljs-replが起動できる
- 依存関係を解決できる(内部でleiningenが使っている物を使用している)
インストール
npm/yarnでインストールすることができる。
# yarn
yarn global add shadow-cljs
# npm
npm install -g shadow-cljs
ざっくりとした利用方法
とりあえずcliツールとして使う場合のみを考慮する
shadow-cljs.ednをプロジェクトのルートに用意する
- ビルドの設定ファイル
-
shadow-cljs init
でスケルトンを生成することができる - 以下のような感じ
{:source-paths
["src"] ;; ソースコードがあるパスを書く
:dependencies
;; 1. Clojure,ClojureScriptはshadow-cljs本体に含まれるため指定しない
;; 2. Leiningenと同じ形式で指定する
[[reagent "0.7.0"]]
:builds
{:my-app ;; build-id。複数可能
{:target :browser ;; nodeやカスタムターゲットを設定できる
:output-dir "shadow-out/js" ;; ビルドを出力をするディレクトリ
:asset-path "/js" ;; 開発時の依存モジュールをGETしに行く際のルートディレクトリ
;; メインのネームスペースを指定する
:modules {:main {:entries [my-app.app]}}
;; コードのホットリロード時に実行される関数を指定する
:devtools {:before-load my-app.app/before-load
:after-load my-app.app/after-load }
;;ClojureScriptコンパイラがサポートしているパラメータを渡せる
:closure-defines {myapp.app.foo "foobar"}}}}
ビルドする
-
shadow-cljs <compile|watch|cljs-repl|release> <build-id>
でビルドする -
compile
- 開発時の設定で一度だけビルドする -
watch
- ソースの変更を検知してビルドを行う。コードのホットリロードはこれで行う -
cljs-repl
- ビルドにreplクライアントを含め、それに接続する -
release
- ClojureScriptコンパイラで言うところの:optimizations :advanced
でビルドする。- 開発用(ホッロリロード/repl)コードがビルドに含まれない
詳細
この辺を読んだら仕事のプロジェクトはビルドできた
感想
- ClojureScriptの開発時に欲しい機能が1つにまとまっている
- leiningen/bootに依存していない
- ビルドの設定が開発時とリリース時で共通にできるのでスッキリする
以上の点からClojureScriptのアプリケーションを開発するだけであれば非常に魅力的なツールだという印象を持った。
Clojureのライブラリとしても利用できるようなので、好みが合うのであればfigwheelやcljsbuildをこれで置換しても良いと思う。
余談
1. warningが親切だった
たまたまwarningが含まれるプロジェクトをビルドしてみたのだが、
出力が親切だったのが新鮮だった。
[:my-app] Build completed. (161 files, 45 compiled, 1 warnings, 23.37s)
------ WARNING #1 --------------------------------------------------------------
File: clojure/reflect.cljs
--------------------------------------------------------------------------------
29 | [sym cb]
30 | (query-reflection (str "var=" (js/encodeURIComponent (str sym)))
31 | #(cb (evaluate-javascript %))))
32 |
33 | (defn macroexpand
-------^------------------------------------------------------------------------
macroexpand already refers to: cljs.core/macroexpand being replaced by: clojure.reflect/macroexpand
--------------------------------------------------------------------------------
34 | "Queries the reflection api with a quoted macro form, then calls the
35 | callback function with the macroexpanded form, as a string."
36 | [form]
37 | (query-reflection (str "macroform=" (js/encodeURIComponent (str form))) println))
38 |
--------------------------------------------------------------------------------
2. Readmeの内容が間違っているっぽかったのでプルリク送った