`shadow-cljs release` の最適化で使わない引数が最適化されてしまいエラーに
詳細はまた追記するかも。
ローカルでは動くのに Firebase にリリースすると動かない。
shadow-cljs release
コマンドで生成される minify された JS を見て気づいた。
仮実装で使っていない引数が全て消えてしまって、結果引数なしで呼び出され、その場合 casual
の define
が関数ではなく Property として機能を生やす仕様のため、関数呼び出しがエラーになるようになってしまった。
casual
の define
の引数ありとなしの場合の、生成される関数/プロパティの仕様はこのドキュメントを見ると分かりやすい。
https://github.com/boo1ean/casual#define
実際の僕のコードはこんなの。
(.define casual
"hoge"
(fn [arg1 arg2] "仮の return value"))
shadow-cljs の最適化の問題というよりは、ClojureScript が中で使っている Google Closure Compiler の ADVANCED_OPTIMIZATIONS
コンパイルの挙動なんだろうな。
Closure Compiler Compilation Levels | Google Developers
(追記) コンパイル結果の違い🔗
(.define casual
"hoge"
(fn [arg1 arg2] "仮の return value"))
上記のコードと同様のこのコードが shadow-cljs.edn
の :compiler-options {:optimizations :simple}
の有無で shadow-cljs release
の結果がどう変わるか試してみた。
この設定のドキュメントはこちら → 13.1. Release Configuration | Shadow CLJS User’s Guide
指定できる値はソースコードのこのあたり https://github.com/thheller/shadow-cljs/blob/086ee94f9a4e5fac66a9c4fa985364a40ab41ce4/src/main/shadow/build/closure.clj#L116-L121
(case level-kw
:advanced CompilationLevel/ADVANCED_OPTIMIZATIONS
:whitespace CompilationLevel/WHITESPACE_ONLY
:simple CompilationLevel/SIMPLE_OPTIMIZATIONS
:none nil
(throw (ex-info "invalid :optimizations level" opts)))]
:optimizations :simple
ありの場合🔗
shadow.js.shim.module$casual.define("hoge",function(a,b){return"仮の return value"});
この場合の呼び出しは
// js
casual.hoge(null, null)
; cljs
(.hoge casual nil nil)
のような感じ。関数としてコールする。
:optimizations :simple
なし → なので :optimizations :advanced
が暗黙的に使われた場合🔗
Ue.define("hoge",function(){return"仮の return value"});
変数名が短くされているのは関係ないのでおいておく。 これだと、呼び出し時は
// js
casual.hoge
; cljs
(.-hoge casual)
とプロパティ参照で使わないといけなくなってしまう。
感想🔗
- Google Closure Compoiler の ADVANCED_OPTIMIZATIONS が使ってない引数をシグネチャからも削除してしまう。
- casual が関数呼び出しじゃなくてプロパティ参照がデフォルト、という変わった API なこと。
2つ合わさってのはまりどころでした。
Google Closure Compoiler のコンパイルオプションなどで挙動を制御できそうな気もする。