How do I get the direct result of a simple clojurescript compilation?
I want to be able to inject javascript code into my app while testing. Following this line of reasoning, I do the following in a repl.
=> (cljs.closure/build '(swap! my-project.my-namespace.my-atom inc) {})
<= "goog.addDependency(\"base.js\", ['goog'], []);\ngoog.addDependency(\"../x8LL7.js\", [], []);"
После, я
=> more out/x8LL7.js
<= cljs.core.swap_BANG_.call(null,my_project.my_namespace.my_atom,cljs.core.inc);
Да, похоже, это то, что я хочу. Я могу ошибаться, но я не думаю, что мне нужна зависимость "base.js", так как она уже включена в тестируемое работающее приложение (которое использует:simple:optimizations).
У меня вопрос, как я могу получить содержимое файла out/x8LL7.js
? Я просто хочу строку, которая написана out/x8LL7.js
так как я не использую строку файла deps, которая возвращается из cljs.closure/build
,
Если это не так просто, то, я думаю, я могу просто проанализировать возвращенную строку deps, открыть файл самостоятельно и затем использовать содержимое; не так уж и важно. Тем не менее, я надеялся, что есть более прямой путь.
3 ответа
В основном, просто записка для себя, но в случае, если кому-то нужно знать, вот как я быстро это исправил.
(def cljs-to-js-dir "_cljs_to_js_out")
(def js-options { :output-dir cljs-to-js-dir})
(defn js-compile [quoted-expr]
(let [ result (cljs.closure/build quoted-expr js-options)
file-name ((re-find #"(/.+\.js)" result) 0)]
(slurp (str cljs-to-js-dir "/" file-name))))
(defmacro to-js [expr]
(js-compile `((fn [] ~expr))))
Используя этот код, вы можете (из repl) набрать:
=> (to-js (swap! my-project.my-namespace.my-atom inc))
<= "(function (){\nreturn cljs.core.swap_BANG_.call(null,my_project.my_namespace.my_atom,cljs.core.inc);\n}).call(null);\n"
Могу поспорить, что вам любопытно, почему я обернул expr(ession) в немедленно вызываемую функцию без аргументов. Это потому, что cljs.closure/build оптимизирует код, если он на самом деле не используется. Например:
=> (js-compile '(fn [a b] (+ a b)))
<= ""
тем не мение
=> (js-compile '((fn [a b] (+ a b)) 2 3))
<= "(function (a,b){\nreturn (a + b);\n}).call(null,2,3);\n"
Детали в стороне, (to-js)
кажется делает то, что я хочу.
Вы можете попробовать онлайн REPL для cljs-in-cljs на http://clojurescript.net/:
Сначала включите режим отладки:
cljs.user=> (set! webrepl/*debug* true)
Теперь, когда вы оцениваете форму, вы получите результат чтения, анализа (только полученную форму) и отправленный JS:
cljs.user=> (def myatom (atom 1))
...
cljs.user=> (swap! myatom inc)
READ: (swap! myatom inc)
ANALYZED: (swap! myatom inc)
EMITTED: "cljs.core.swap_BANG_.call(null,cljs.user.myatom,cljs.core.inc)"
2
Отказ от ответственности: я создатель cljs-in-cljs/clojurescript.net
Более прямым способом было бы внедрить код js (например, 'var DEBUG=true;'), а затем сослаться на него из clojurescript. Внедрение clojurescript рискованно, потому что нет никакого договора на то, какой код js будет скомпилирован clojurescript - вы могли бы иметь совершенно другой код с другими настройками оптимизации или версией clojurescript.