boot-clj / boot-cljs Goto Github PK
View Code? Open in Web Editor NEWBoot task to compile ClojureScript programs.
License: Eclipse Public License 1.0
Boot task to compile ClojureScript programs.
License: Eclipse Public License 1.0
Using
boot cljs -O :none -s -u
with 0.0-2411-8
, cat target/js/app.js
delivered:
// boot-cljs shim
document.write("<script src='js/react.min.inc.js'></script>");
document.write("<script src='js/out/goog/base.js'></script>");
document.write("<script src='js/boot-cljs-app.js'></script>");
document.write("<script>goog.require('phone.main');</script>");
which worked. ;)
But, with o.o-2629-3
, cat target/js/app.js
delivers:
// boot-cljs shim
(function() {
var shimRegex = new RegExp('(.*)app.js$');
function findPrefix() {
var els = document.getElementsByTagName('script');
for (var i = 0; i < els.length; i++) {
var src = els[i].getAttribute('src');
var match = src && src.match(shimRegex);
if (match) {
return match[1];
}
}
return '';
}
var prefix = findPrefix();
document.write("<script src='" + prefix + "js/react.min.inc.js'></script>");
document.write("<script src='" + prefix + "js/out/goog/base.js'></script>");
document.write("<script src='" + prefix + "js/boot-cljs-app.js'></script>");
document.write("<script>goog.require('phone.main');</script>");
})();
which does not work.
Total guess, but was that "js/" after the prefix thing an accident?
When I inspect the loaded dom, I see:
<head>
<script src="js/js/react.min.inc.js"></script>
<script src="js/js/out/goog/base.js"></script>
<script src="js/js/boot-cljs-app.js"></script>
<script>goog.require('phone.main');</script>
</head>
There's an extra js
in there.
The scripts included in index.html
look like:
<script type="text/javascript" src="cordova.js"></script>
<script type="text/javascript" src="js/fastclick.js"></script>
<script type="text/javascript" src="js/app.js"></script>
and resources are:
resources/
├── css
│ └── app.css
├── index.html
└── js
├── fastclick.js
└── react.min.inc.js
Currently is seems to be only possible to generate js files relative to the target directory directly.
If you want to put the js under another path (output-to) and then serve from a subdirectory of target then the shim will break.
this is not an issue, other than for unified mode.
My html is @ public/index.html. I use :output-to "public/js/main.js"
as an option for boot-cljs. When using unified mode, this results in a shim like this
...
document.write("<script src='out/goog/base.js'></script>");
document.write("<script src='public/js/cljsc-output-c4afbd925.js'></script>");
...
These paths are not relative to my html, so they can't be found. Maybe there is a better way I should structure my web app that is more boot friendly but I'm not sure. Open to suggestions. I only have two requirements: needs to work well with a dev server & needs to be packagable as a standalone jar for production (I like the speed & simplicity of httpkit). Cheers :)
I have two .cljs.edn
files, one targets browser and one with :compiler-options {:target :nodejs}
. It worked great with CLJS 0.0-2740, but after clojure/clojurescript@1611bdc incremental compilation doesn't work. After each change there is full recompilation, first for browser and then with {:target :nodejs}
.
Maybe for builds that differ in build-affecting-options
, it should be separate context/:output-dir.
Right now, depending on hardware of course, the initial compilation of a ClojureScript app can take anywhere from 15 seconds to multiple minutes.
The Leiningen plugin gets around this (somewhat) because already-compiled portions of the ClojureScript source are not recompiled, even from a fresh lein cljsbuild once
.
I know Boot has a different philosophy, but is there any workaround possible for this?
Here is repository with a problem, when I compile things, it says:
Compiling boot-cljs-atom.js...
Compiling boot-cljs-ui.js...
But then
switter> ls target/boot-cljs*
target/boot-cljs-ui.js
This seems like a bug.
Cljs code can depend on .clj code when it's using macros.
Lein-cljsbuild will mark all cljs files changed when any clj file (in cljs source-paths) changes. Thus it will recompile any cljs code using macros (in the project) but it doesn't need to recompile cljs.core etc. as they are on cache.
We could just create new pod when clj changes, that way we can be very sure that there is no stale state. With cljs.core cache #22 this might be fast enough.
As a build tool author, I'm wondering if you have an opinion/input to this discussion:
http://dev.clojure.org/jira/browse/CLJS-851
When I have a build with the option :compiler-options {:target :nodejs}
a boot-cljs shim is generated. I think it would make sense to skip this since it's useless in a node environment.
In an empty directory, I ran the "Try It" section.
$ mkdir src
$ echo -e '(ns foop)\n(.log js/console "hello world")' > src/foop.cljs
$ boot -s src -d adzerk/boot-cljs cljs
Writing main.cljs.edn...
clojure.lang.ExceptionInfo: java.util.concurrent.ExecutionException: org.sonatype.aether.resolution.DependencyResolutionException: Could not find artifact org.clojure:clojurescript:jar:0.0.0 in clojars (http://clojars.org/repo/)
data: {:file
"../var/folders/n9/3v0_clqj0f3gm3956_06hq680000gp/T/boot.user36358634228092199.clj",
:line 5}
java.util.concurrent.ExecutionException: java.util.concurrent.ExecutionException: org.sonatype.aether.resolution.DependencyResolutionException: Could not find artifact org.clojure:clojurescript:jar:0.0.0 in clojars (http://clojars.org/repo/)
java.util.concurrent.ExecutionException: org.sonatype.aether.resolution.DependencyResolutionException: Could not find artifact org.clojure:clojurescript:jar:0.0.0 in clojars (http://clojars.org/repo/)
org.sonatype.aether.resolution.DependencyResolutionException: Could not find artifact org.clojure:clojurescript:jar:0.0.0 in clojars (http://clojars.org/repo/)
result: #<DependencyResult [adzerk:boot-cljs:jar:0.0-2814-1 < clojars (http://clojars.org/repo/, releases+snapshots), null < null]>
org.sonatype.aether.resolution.ArtifactResolutionException: Could not find artifact org.clojure:clojurescript:jar:0.0.0 in clojars (http://clojars.org/repo/)
result: #<ArtifactResult adzerk:boot-cljs:jar:0.0-2814-1 < clojars (http://clojars.org/repo/, releases+snapshots)>
results: [#<ArtifactResult adzerk:boot-cljs:jar:0.0-2814-1 < clojars (http://clojars.org/repo/, releases+snapshots)> #<ArtifactResult null < null>]
org.sonatype.aether.transfer.ArtifactNotFoundException: Could not find artifact org.clojure:clojurescript:jar:0.0.0 in clojars (http://clojars.org/repo/)
artifact: #<DefaultArtifact org.clojure:clojurescript:jar:0.0.0>
repository: #<RemoteRepository clojars (http://clojars.org/repo/, releases+snapshots)>
org.sonatype.aether.connector.wagon.WagonRepositoryConnector$4.wrap WagonRepositoryConnector.java: 947
org.sonatype.aether.connector.wagon.WagonRepositoryConnector$4.wrap WagonRepositoryConnector.java: 941
org.sonatype.aether.connector.wagon.WagonRepositoryConnector$GetTask.run WagonRepositoryConnector.java: 669
org.sonatype.aether.util.concurrency.RunnableErrorForwarder$1.run RunnableErrorForwarder.java: 60
...
Looks like it's looking for clojurescript 0.0.0 for some reason.
Here's my boot version:
$ boot -V
#https://github.com/boot-clj/boot
#Mon Feb 23 22:28:14 CST 2015
BOOT_CLOJURE_VERSION=1.6.0
BOOT_VERSION=2.0.0-rc9
I have 4 outputs: for the browser (app.js) and for the server (node.js), as well as test for browser (app.test.js) and server (app.node.js). When I have a compile error I see this after hitting save:
Compiling SASS...
Compiling boot-cljs-app-node.js...
clojure.lang.ExceptionInfo: failed compiling file:/Users/stephan/.boot/tmp/Users/stephan/Dev/workspace/jobflock/frontend/f8r/-x24pa9/app/core.cljs
data: {#<Keyword :file> #<File /Users/stephan/.boot/tmp/Users/stephan/Dev/workspace/jobflock/frontend/f8r/-x24pa9/app/core.cljs>}
clojure.lang.ExceptionInfo: EOF while reading, starting at line 12
data: {#<Keyword :column> 16, #<Keyword :line> 42, #<Keyword :file> "/Users/stephan/.boot/tmp/Users/stephan/Dev/workspace/jobflock/frontend/f8r/-x24pa9/app/core.cljs", #<Keyword :type> #<Keyword :reader-exception>}
clojure.core/ex-info core.clj: 4403
clojure.tools.reader.reader-types/reader-error reader_types.clj: 336
...
clojure.tools.reader/read-delimited reader.clj: 167
clojure.tools.reader/read-list reader.clj: 173
clojure.tools.reader/read reader.clj: 747
clojure.tools.reader/read reader.clj: 732
cljs.analyzer/forms-seq/forms-seq*/fn/fn analyzer.clj: 1742
cljs.analyzer/forms-seq/forms-seq*/fn analyzer.clj: 1736
...
clojure.core/seq core.clj: 133
cljs.compiler/compile-file*/fn compiler.clj: 946
cljs.compiler/with-core-cljs compiler.clj: 906
cljs.compiler/compile-file* compiler.clj: 927
cljs.compiler/compile-file compiler.clj: 1033
cljs.closure/compile-file closure.clj: 348
cljs.closure/eval3108/fn closure.clj: 399
cljs.closure/eval3044/fn/G closure.clj: 306
cljs.closure/eval3103/fn closure.clj: 404
cljs.closure/eval3044/fn/G closure.clj: 306
cljs.closure/get-compiled-cljs closure.clj: 468
cljs.closure/cljs-dependencies closure.clj: 512
cljs.closure/add-dependencies closure.clj: 534
...
clojure.core/apply core.clj: 626
cljs.closure/build closure.clj: 1033
cljs.closure/build closure.clj: 972
adzerk.boot-cljs.impl/compile-cljs impl.clj: 60
...
clojure.core/apply core.clj: 624
boot.pod/eval-fn-call pod.clj: 176
boot.pod/call-in* pod.clj: 183
...
boot.pod/call-in* pod.clj: 186
adzerk.boot-cljs/compile boot_cljs.clj: 63
adzerk.boot-cljs/eval258/fn/fn/fn/fn boot_cljs.clj: 133
adzerk.boot-cljs/eval258/fn/fn/fn boot_cljs.clj: 129
adzerk.boot-cljs/eval234/fn/fn/fn boot_cljs.clj: 81
adzerk.boot-reload/eval382/fn/fn/fn boot_reload.clj: 74
adzerk.boot-reload/eval382/fn/fn/fn boot_reload.clj: 67
boot.user/eval799/fn/fn/fn boot.user5961291994962867483.clj: 17
boot.task.built-in/fn/fn/fn/fn/fn/fn built_in.clj: 164
boot.task.built-in/fn/fn/fn/fn/fn built_in.clj: 164
boot.task.built-in/fn/fn/fn/fn built_in.clj: 161
pandeiro.boot-http/eval426/fn/fn/fn boot_http.clj: 51
boot.user/eval819/fn/fn/fn boot.user5961291994962867483.clj: 19
boot.core/run-tasks core.clj: 618
...
boot.user/eval899/fn boot.user5961291994962867483.clj: 31
clojure.core/binding-conveyor-fn/fn core.clj: 1910
...
Elapsed time: 1.042 sec
Compiling SASS...
Compiling boot-cljs-app-node.js...
Compiling boot-cljs-app.js...
Compiling boot-cljs-testable-node.js...
Compiling boot-cljs-testable.js...
..........
PhantomJS 1.9.8 (Mac OS X): Executed 10 of 10 SUCCESS (0.048 secs / 0.024 secs)
․․․․․․․․․․․
10 passing (196ms)
1 failing
1) fn render should return rendered HTML:
TypeError: Cannot read property 'cljs$core$IFn$_invoke$arity$1' of undefined
at /Users/stephan/Dev/workspace/jobflock/frontend/target/out/app/server/render.js:33:18
at Function.app.server.render.render_app.render_app__3 [as cljs$core$IFn$_invoke$arity$3] (/Users/stephan/Dev/workspace/jobflock/frontend/target/out/app/server/render.js:34:3)
at Function.app.server.render.render_app.render_app__1 [as cljs$core$IFn$_invoke$arity$1] (/Users/stephan/Dev/workspace/jobflock/frontend/target/out/app/server/render.js:16:19)
at Object.render (/Users/stephan/Dev/workspace/jobflock/frontend/target/out/app/server/render.js:62:47)
at Context.<anonymous> (/Users/stephan/Dev/workspace/jobflock/frontend/target/out/app/server/render_spec.js:24:42)
at callFn (/Users/stephan/.nvm/v0.10.33/lib/node_modules/mocha/lib/runnable.js:251:21)
at Test.Runnable.run (/Users/stephan/.nvm/v0.10.33/lib/node_modules/mocha/lib/runnable.js:244:7)
at Runner.runTest (/Users/stephan/.nvm/v0.10.33/lib/node_modules/mocha/lib/runner.js:374:10)
at /Users/stephan/.nvm/v0.10.33/lib/node_modules/mocha/lib/runner.js:452:12
at next (/Users/stephan/.nvm/v0.10.33/lib/node_modules/mocha/lib/runner.js:299:14)
at /Users/stephan/.nvm/v0.10.33/lib/node_modules/mocha/lib/runner.js:309:7
at next (/Users/stephan/.nvm/v0.10.33/lib/node_modules/mocha/lib/runner.js:248:23)
at Object._onImmediate (/Users/stephan/.nvm/v0.10.33/lib/node_modules/mocha/lib/runner.js:276:5)
at processImmediate [as _immediateCallback] (timers.js:345:15)
java.lang.Exception: sh: non-zero exit status (1)
boot.util/dosh util.clj: 162
...
boot.user/eval780/fn/fn/fn boot.user5961291994962867483.clj: 15
adzerk.boot-cljs/eval258/fn/fn/fn boot_cljs.clj: 126
adzerk.boot-cljs/eval234/fn/fn/fn boot_cljs.clj: 81
adzerk.boot-reload/eval382/fn/fn/fn boot_reload.clj: 74
adzerk.boot-reload/eval382/fn/fn/fn boot_reload.clj: 67
boot.user/eval799/fn/fn/fn boot.user5961291994962867483.clj: 17
boot.task.built-in/fn/fn/fn/fn/fn/fn built_in.clj: 164
boot.task.built-in/fn/fn/fn/fn/fn built_in.clj: 164
boot.task.built-in/fn/fn/fn/fn built_in.clj: 161
pandeiro.boot-http/eval426/fn/fn/fn boot_http.clj: 51
boot.user/eval819/fn/fn/fn boot.user5961291994962867483.clj: 19
boot.core/run-tasks core.clj: 618
...
boot.user/eval899/fn boot.user5961291994962867483.clj: 31
clojure.core/binding-conveyor-fn/fn core.clj: 1910
...
Elapsed time: 8.578 sec
Compiling SASS...
Compiling boot-cljs-app-node.js...
clojure.lang.ExceptionInfo: failed compiling file:/Users/stephan/.boot/tmp/Users/stephan/Dev/workspace/jobflock/frontend/f8r/-x24pa9/app/core.cljs
data: {#<Keyword :file> #<File /Users/stephan/.boot/tmp/Users/stephan/Dev/workspace/jobflock/frontend/f8r/-x24pa9/app/core.cljs>}
clojure.lang.ExceptionInfo: EOF while reading, starting at line 12
data: {#<Keyword :column> 16, #<Keyword :line> 42, #<Keyword :file> "/Users/stephan/.boot/tmp/Users/stephan/Dev/workspace/jobflock/frontend/f8r/-x24pa9/app/core.cljs", #<Keyword :type> #<Keyword :reader-exception>}
clojure.core/ex-info core.clj: 4403
clojure.tools.reader.reader-types/reader-error reader_types.clj: 336
...
clojure.tools.reader/read-delimited reader.clj: 167
clojure.tools.reader/read-list reader.clj: 173
clojure.tools.reader/read reader.clj: 747
clojure.tools.reader/read reader.clj: 732
cljs.analyzer/forms-seq/forms-seq*/fn/fn analyzer.clj: 1742
cljs.analyzer/forms-seq/forms-seq*/fn analyzer.clj: 1736
...
clojure.core/seq core.clj: 133
cljs.compiler/compile-file*/fn compiler.clj: 946
cljs.compiler/with-core-cljs compiler.clj: 906
cljs.compiler/compile-file* compiler.clj: 927
cljs.compiler/compile-file compiler.clj: 1033
cljs.closure/compile-file closure.clj: 348
cljs.closure/eval3108/fn closure.clj: 399
cljs.closure/eval3044/fn/G closure.clj: 306
cljs.closure/eval3103/fn closure.clj: 404
cljs.closure/eval3044/fn/G closure.clj: 306
cljs.closure/get-compiled-cljs closure.clj: 468
cljs.closure/cljs-dependencies closure.clj: 512
cljs.closure/add-dependencies closure.clj: 534
...
clojure.core/apply core.clj: 626
cljs.closure/build closure.clj: 1033
cljs.closure/build closure.clj: 972
adzerk.boot-cljs.impl/compile-cljs impl.clj: 60
...
clojure.core/apply core.clj: 624
boot.pod/eval-fn-call pod.clj: 176
boot.pod/call-in* pod.clj: 183
...
boot.pod/call-in* pod.clj: 186
adzerk.boot-cljs/compile boot_cljs.clj: 63
adzerk.boot-cljs/eval258/fn/fn/fn/fn boot_cljs.clj: 133
adzerk.boot-cljs/eval258/fn/fn/fn boot_cljs.clj: 129
adzerk.boot-cljs/eval234/fn/fn/fn boot_cljs.clj: 81
adzerk.boot-reload/eval382/fn/fn/fn boot_reload.clj: 74
adzerk.boot-reload/eval382/fn/fn/fn boot_reload.clj: 67
boot.user/eval799/fn/fn/fn boot.user5961291994962867483.clj: 17
boot.task.built-in/fn/fn/fn/fn/fn/fn built_in.clj: 164
boot.task.built-in/fn/fn/fn/fn/fn built_in.clj: 164
boot.task.built-in/fn/fn/fn/fn built_in.clj: 161
pandeiro.boot-http/eval426/fn/fn/fn boot_http.clj: 51
boot.user/eval819/fn/fn/fn boot.user5961291994962867483.clj: 19
boot.core/run-tasks core.clj: 618
...
boot.user/eval899/fn boot.user5961291994962867483.clj: 31
clojure.core/binding-conveyor-fn/fn core.clj: 1910
...
Elapsed time: 0.846 sec
Compiling SASS...
Compiling boot-cljs-app-node.js...
Compiling boot-cljs-app.js...
Compiling boot-cljs-testable-node.js...
Compiling boot-cljs-testable.js...
..........
PhantomJS 1.9.8 (Mac OS X): Executed 10 of 10 SUCCESS (0.043 secs / 0.018 secs)
․․․․․․․․․․․
10 passing (144ms)
1 failing
1) fn render should return rendered HTML:
TypeError: Cannot read property 'cljs$core$IFn$_invoke$arity$1' of undefined
at /Users/stephan/Dev/workspace/jobflock/frontend/target/out/app/server/render.js:33:18
at Function.app.server.render.render_app.render_app__3 [as cljs$core$IFn$_invoke$arity$3] (/Users/stephan/Dev/workspace/jobflock/frontend/target/out/app/server/render.js:34:3)
at Function.app.server.render.render_app.render_app__1 [as cljs$core$IFn$_invoke$arity$1] (/Users/stephan/Dev/workspace/jobflock/frontend/target/out/app/server/render.js:16:19)
at Object.render (/Users/stephan/Dev/workspace/jobflock/frontend/target/out/app/server/render.js:62:47)
at Context.<anonymous> (/Users/stephan/Dev/workspace/jobflock/frontend/target/out/app/server/render_spec.js:24:42)
at callFn (/Users/stephan/.nvm/v0.10.33/lib/node_modules/mocha/lib/runnable.js:251:21)
at Test.Runnable.run (/Users/stephan/.nvm/v0.10.33/lib/node_modules/mocha/lib/runnable.js:244:7)
at Runner.runTest (/Users/stephan/.nvm/v0.10.33/lib/node_modules/mocha/lib/runner.js:374:10)
at /Users/stephan/.nvm/v0.10.33/lib/node_modules/mocha/lib/runner.js:452:12
at next (/Users/stephan/.nvm/v0.10.33/lib/node_modules/mocha/lib/runner.js:299:14)
at /Users/stephan/.nvm/v0.10.33/lib/node_modules/mocha/lib/runner.js:309:7
at next (/Users/stephan/.nvm/v0.10.33/lib/node_modules/mocha/lib/runner.js:248:23)
at Object._onImmediate (/Users/stephan/.nvm/v0.10.33/lib/node_modules/mocha/lib/runner.js:276:5)
at processImmediate [as _immediateCallback] (timers.js:345:15)
java.lang.Exception: sh: non-zero exit status (1)
boot.util/dosh util.clj: 162
...
boot.user/eval780/fn/fn/fn boot.user5961291994962867483.clj: 15
adzerk.boot-cljs/eval258/fn/fn/fn boot_cljs.clj: 126
adzerk.boot-cljs/eval234/fn/fn/fn boot_cljs.clj: 81
adzerk.boot-reload/eval382/fn/fn/fn boot_reload.clj: 74
adzerk.boot-reload/eval382/fn/fn/fn boot_reload.clj: 67
boot.user/eval799/fn/fn/fn boot.user5961291994962867483.clj: 17
boot.task.built-in/fn/fn/fn/fn/fn/fn built_in.clj: 164
boot.task.built-in/fn/fn/fn/fn/fn built_in.clj: 164
boot.task.built-in/fn/fn/fn/fn built_in.clj: 161
pandeiro.boot-http/eval426/fn/fn/fn boot_http.clj: 51
boot.user/eval819/fn/fn/fn boot.user5961291994962867483.clj: 19
boot.core/run-tasks core.clj: 618
...
boot.user/eval899/fn boot.user5961291994962867483.clj: 31
clojure.core/binding-conveyor-fn/fn core.clj: 1910
...
Elapsed time: 6.095 sec
Compiling SASS...
Compiling boot-cljs-app-node.js...
Compiling boot-cljs-app.js...
Compiling boot-cljs-testable-node.js...
Compiling boot-cljs-testable.js...
..........
PhantomJS 1.9.8 (Mac OS X): Executed 10 of 10 SUCCESS (0.031 secs / 0.014 secs)
․․․․․․․․․․․
10 passing (140ms)
1 failing
1) fn render should return rendered HTML:
TypeError: Cannot read property 'cljs$core$IFn$_invoke$arity$1' of undefined
at /Users/stephan/Dev/workspace/jobflock/frontend/target/out/app/server/render.js:33:18
at Function.app.server.render.render_app.render_app__3 [as cljs$core$IFn$_invoke$arity$3] (/Users/stephan/Dev/workspace/jobflock/frontend/target/out/app/server/render.js:34:3)
at Function.app.server.render.render_app.render_app__1 [as cljs$core$IFn$_invoke$arity$1] (/Users/stephan/Dev/workspace/jobflock/frontend/target/out/app/server/render.js:16:19)
at Object.render (/Users/stephan/Dev/workspace/jobflock/frontend/target/out/app/server/render.js:62:47)
at Context.<anonymous> (/Users/stephan/Dev/workspace/jobflock/frontend/target/out/app/server/render_spec.js:24:42)
at callFn (/Users/stephan/.nvm/v0.10.33/lib/node_modules/mocha/lib/runnable.js:251:21)
at Test.Runnable.run (/Users/stephan/.nvm/v0.10.33/lib/node_modules/mocha/lib/runnable.js:244:7)
at Runner.runTest (/Users/stephan/.nvm/v0.10.33/lib/node_modules/mocha/lib/runner.js:374:10)
at /Users/stephan/.nvm/v0.10.33/lib/node_modules/mocha/lib/runner.js:452:12
at next (/Users/stephan/.nvm/v0.10.33/lib/node_modules/mocha/lib/runner.js:299:14)
at /Users/stephan/.nvm/v0.10.33/lib/node_modules/mocha/lib/runner.js:309:7
at next (/Users/stephan/.nvm/v0.10.33/lib/node_modules/mocha/lib/runner.js:248:23)
at Object._onImmediate (/Users/stephan/.nvm/v0.10.33/lib/node_modules/mocha/lib/runner.js:276:5)
at processImmediate [as _immediateCallback] (timers.js:345:15)
java.lang.Exception: sh: non-zero exit status (1)
boot.util/dosh util.clj: 162
...
boot.user/eval780/fn/fn/fn boot.user5961291994962867483.clj: 15
adzerk.boot-cljs/eval258/fn/fn/fn boot_cljs.clj: 126
adzerk.boot-cljs/eval234/fn/fn/fn boot_cljs.clj: 81
adzerk.boot-reload/eval382/fn/fn/fn boot_reload.clj: 74
adzerk.boot-reload/eval382/fn/fn/fn boot_reload.clj: 67
boot.user/eval799/fn/fn/fn boot.user5961291994962867483.clj: 17
boot.task.built-in/fn/fn/fn/fn/fn/fn built_in.clj: 164
boot.task.built-in/fn/fn/fn/fn/fn built_in.clj: 164
boot.task.built-in/fn/fn/fn/fn built_in.clj: 161
pandeiro.boot-http/eval426/fn/fn/fn boot_http.clj: 51
boot.user/eval819/fn/fn/fn boot.user5961291994962867483.clj: 19
boot.core/run-tasks core.clj: 618
...
boot.user/eval899/fn boot.user5961291994962867483.clj: 31
clojure.core/binding-conveyor-fn/fn core.clj: 1910
...
Elapsed time: 5.622 sec
The build stops on the compile error, so far so good. But then it continues to build all 4 outputs multiple times again. Even successfully! What's that all about?
base-opts contains empty vectors for :externs and :preamble. base-opts is merged with various derived vectors into cljs-opts. The preamble files are determined by searching for file extensions ".inc.js" in the input-files file set, and the external files by searching for ".ext.js" extensions in the same file set.
I suggest adding (initially) two arguments to the task options; "e externs" and "m preamble." These would provide the initial contents of the vectors associated with the respective keys in base-opts, by searching for the named files in the input-files set, assuming that jar files in dependencies make their way into the input-files set. If not, these jars must be searched separately from input-files for the named extern or preamble files. Once this initial set for each of "externs and :preamble is determined, the existing by-ext searching can proceed and be merged with the initial option values.
I can try this out myself, but I'm not sure about the way dependencies are handled. Are they included in input-files?
Okay, boot-cljs is finally updated. There is still however much to improve.
Some general ideas:
cljs.compiler.api
(comp (cljs :id "browser") (cljs :id "node"))
and cljs.edn files should probably have :id
property.:main
option if shim is to be used(def ^:private deps
"ClojureScript dependency to load in the pod if
none is provided via project"
(delay (remove pod/dependency-loaded? '[[org.clojure/clojurescript "0.0-2814"]])))
This just checks if Clojurescript is present, not if it's an equal/above version. There should be a check like that.
Currently the directory where to put includes is hoplon/includes
.
As boot isn't just a hoplon tool it seems to me that this should be more generic.
What about boot-cljs/includes
or something that makes the purpose of the directory more clear.
Also for backwards compatibility it'd probably be necessary to continue supporting hoplon/includes
.
Shim works fine when used from index.html
.
But when used from e.g. posts/first.html
the relative urls don't work.
// boot-cljs shim
document.write("<script src='js/highlight.pack.inc.js'></script>");
document.write("<script src='out/goog/base.js'></script>");
document.write("<script src='boot-cljs-main.js'></script>");
document.write("<script>goog.require('main');</script>");
index.html: <script src="main.js"></script>
posts/first.html: <script src="../main.js"></script>
I wonder if main.js could somehow guess how it is being loaded.
This is kinda funky:
JS reserved names:
https://github.com/clojure/clojurescript/blob/c222f6f0a0106ec93d3d5ad64291e17edf266f1d/src/clj/cljs/compiler.clj#L24-37
So if your :output-to
path contains any of those names, when boot-clj creates an intermediate cljs file with the same namespace as that path, the ns will get munged. So in my case goog.require could not find: public.js.main
because it is provided as goog.provide('public$.js.main');
All cljs
files found in :resources-paths
locations will be required in the default main.cljs.edn
. This can lead to compilation errors as those files are not intended to be compiled.
I talked briefly about this with @micha before and now have some more concerns, that the file extension way of doing things might not be as flexible as it should.
If you're including jQuery you might want to use a local copy for development but on production loading from a CDN is often faster for popular libraries as they're cached on clients. Currently there is no way to specify externs without also adding the library itself as preamble. This also means that every time you change and deploy your javascript users will have to download all the libraries your code uses again.
It's fair to say that dependency management is "a totally solved problem" but I think in this case there are a lot of specific scenarios that should be coverable with boot-clis
. And the way it handles the preamble and externs currently is to inflexible/automagic to allow this.
I'd like to use this issue to discuss this further. I might be wrong as well.
Latest release [adzerk/boot-cljs "0.0-2814-0"]
can't be found on clojars.org.
The shim should somehow be aware if it has been run before so it can be reloaded by tools like boot-reload
without any special handling.
An alternative could be to track file contents vs. mtimes to determine if a file has changed but @piranha and I weren't sure if you wouldn't run into trouble with this as old function references might stick around.
Also idempotence isn't gonna hurt anyone I assume.
I really like the .cljs.edn
approach to multiple targets. It's exactly what I was looking for. But... I don't think it's working if you use any optimization (I tried :simple
, :advanced
). Each target includes itself and the previous target.
Looking at the js output for optimizations :none
, the issue is occurring there too, but it's not run because the goog.require
loads the correct namespace.
I've tried using older versions to make sure this isn't another variant of #38 .
[adzerk/boot-cljs "0.0-2814-3"] ;; latest release
to dodge other bugsapp.cljs
(defn my-alert [] (js/alert "You rang?"))
html/aaa_not_included.cljs.edn
(intentionally first, alphabetically){:require [app] :init-fns [app/my-alert]}
html/included.cljs.edn
{:require [app]}
html/index.html
change app.js
to included.js
boot serve -d target/ watch speak reload cljs -sO simple
RESULT:
An alert pops up. Someone called app/my-alert
!
So I am attempting some Chrome extension development. Chrome has specific Content Security Policy rules that forbid two things that boot-cljs does.
manifest.json
file. No real problem. "content_security_policy": "script-src 'self' 'unsafe-eval'; object-src 'self'"
script
tag. The only example of this I can find is in the following in main.js
(generated with :optimizations :none). function writeScript(src) {
var newElem;
if (window.__boot_cljs_shim_loaded === undefined)
document.write(src);
else {
newElem = document.createElement('div');
newElem.innerHTML = src;
if (newElem.src !== undefined && loaded[newElem.src] === undefined) {
document.getElementsByTagName('head')[0].appendChild(newElem); }}}
writeScript("<script src='" + prefix + "out/goog/base.js'></script>");
writeScript("<script src='" + prefix + "boot-cljs-main.js'></script>");
writeScript("<script>goog.require('boot.cljs.main');</script>");
window.__boot_cljs_shim_loaded = true; })();
So, to fix this, after my code is generated, I then manually changed
writeScript("<script>goog.require('boot.cljs.main');</script>");
into
writeScript("<script src="file_that_goog_requires_boot_cljs_main.js"></script>");
and added a file named file_that_goog_requires_boot_cljs_main.js
that contains
goog.require('boot.cljs.main');
After making the above changes, I reload the extension and play with it. Cool. I can create a repl into the extension and execute code. Everything is good.
So, I know what to do, my question is how should I do it? Obviously manually editing the file every time is dumb. Should I create another task? Is there some way I could reach into boot-cljs and effect things? Is there some other totally evident option? Thank you for your time and help.
Not sure if this is an issue with the Cljs task, but it might be fixed here. If you have a watch cljs
task running and a new empty cljs
file is created, an AssertionError
is triggered by the Clojurescript compiler as the file doesn't have a namespace declaration. This error escapes the compiler invocation and terminates the watch
.
Not sure if the boot-cljs.impl/compile-cljs
or the watch task should be made more robust, but it would be great if such scenarios were recoverable.
java.util.concurrent.ExecutionException: java.lang.AssertionError: Assert failed:
some.cljs does not provide a namespace
(first provides)
java.lang.AssertionError: Assert failed: some.cljs does not provide a namespace
(first provides)
cljs.closure/javascript-file closure.clj: 267
cljs.closure/map->javascript-file closure.clj: 280
cljs.closure/compiled-file closure.clj: 317
clojure.core/map/fn core.clj: 2557
...
clojure.core/seq core.clj: 133
clojure.core/concat/cat/fn core.clj: 694
...
clojure.core/seq core.clj: 133
clojure.core/concat/fn core.clj: 685
...
clojure.core/apply core.clj: 626
cljs.closure/build closure.clj: 973
cljs.closure/build closure.clj: 928
adzerk.boot-cljs.impl/compile-cljs/fn impl.clj: 146
When I have an exclusion on clojurescript
in my dependencies (e.g. [secretary "1.2.0" :exclusions [org.clojure/clojurescript]]
) I get the following exception when running a cljs
task:
java.util.concurrent.ExecutionException: org.sonatype.aether.resolution.DependencyResolutionException: Could not find artifact org.clojure:clojurescript:jar:0.0.0 in clojars (http://clojars.org/repo/)
org.sonatype.aether.resolution.DependencyResolutionException: Could not find artifact org.clojure:clojurescript:jar:0.0.0 in clojars (http://clojars.org/repo/)
Not sure if this is an issue specific to this plugin or a more general restriction.
> boot -V
#https://github.com/boot-clj/boot
#Thu Nov 20 15:26:31 JST 2014
BOOT_CLOJURE_VERSION=1.6.0
BOOT_VERSION=2.0.0-pre24
> echo -e '(ns foop)\n(.log js/console "hello world")' > foop.cljs
> boot -d adzerk/boot-cljs cljs
Compiling main.js...
WARNING: No such namespace: adzerk.boot-reload.client at line 1 ./boot-cljs-example/.boot/tmp/jz7/-oanhzy/adzerk/boot_reload.cljs
WARNING: No such namespace: weasel.repl at line 1 ./boot-cljs-example/.boot/tmp/jz7/q2pz4j/adzerk/boot_cljs_repl.cljs
WARNING: No such namespace: adzerk.boot-reload.websocket at line 1 ./boot-cljs-example/.boot/tmp/jz7/-kut359/out/adzerk/boot_reload/client.cljs
WARNING: No such namespace: weasel.impls.websocket at line 1 ./boot-cljs-example/.boot/tmp/jz7/-kut359/out/weasel/repl.cljs
clojure.lang.ExceptionInfo: java.io.FileNotFoundException: The file .boot/tmp/mhy/3lgroc/cljs/core.cljs does not exist.
data: {:file "/tmp/boot.user4375534420312420218.clj", :line 7}
java.util.concurrent.ExecutionException: java.io.FileNotFoundException: The file .boot/tmp/mhy/3lgroc/cljs/core.cljs does not exist.
java.io.FileNotFoundException: The file .boot/tmp/mhy/3lgroc/cljs/core.cljs does not exist.
cljs.compiler/compile-file compiler.clj: 977
cljs.closure/compile-file closure.clj: 333
cljs.closure/compile-from-jar closure.clj: 373
cljs.closure/eval2999/fn closure.clj: 390
cljs.closure/eval2939/fn/G closure.clj: 293
cljs.closure/get-compiled-cljs closure.clj: 453
cljs.closure/cljs-dependencies closure.clj: 484
cljs.closure/add-dependencies closure.clj: 506
...
clojure.core/apply core.clj: 626
cljs.closure/build closure.clj: 973
cljs.closure/build closure.clj: 928
adzerk.boot-cljs.impl/compile-cljs/fn impl.clj: 146
adzerk.boot-cljs.impl/compile-cljs impl.clj: 144
...
clojure.core/apply core.clj: 624
boot.pod/eval-fn-call pod.clj: 174
boot.pod/call-in pod.clj: 181
...
boot.pod/call-in pod.clj: 184
adzerk.boot-cljs/eval59/fn/fn/fn/fn boot_cljs.clj: 117
adzerk.boot-cljs/eval59/fn/fn/fn boot_cljs.clj: 93
boot.core/run-tasks core.clj: 327
boot.user/eval124/fn boot.user4375534420312420218.clj: 9
clojure.core/binding-conveyor-fn/fn core.clj: 1910
...
E. g., if :foreign-libs
contains entry
{:file "jquery-ui.min.js"
:provides ["jquery.ui"]
:requires ["cljsjs.jquery"]}
then in browser console we can see 404 of http://localhost:3000/-p9hf6h/jquery-ui.min.js on page which depends on jquery.ui
With 2760-0 everything works fine, producing http://localhost:3000/js/out/jquery-ui.min.js
Having set up a project as described in Examples, and executed
$ boot cljs -usO none
I get
clojure.lang.ExceptionInfo: Could not locate boot_cljs__init.class or boot_cljs.clj on classpath:
data: {:file
"/var/folders/hj/3wt5y1k122n92h0856hgz3cw0000gn/T/boot.user5766784267661236801.clj",
:line 7}
Have I missed a step, or is there a step missing from the description?
I have a Clojure Ring handler as the backend serving the HTML and scripts, which I use via boot-http. The shim written by boot-cljs to target/boot-cljs-main.js
requests an odd file from the server: /Users/iv/.boot/cache/tmp/Users/iv/src/foo/7n7/dzj78b/out/cljs_deps.js
. I don't want my server to serve anything outside the project directory, so this request returns 404, which means my ClojureScript won't load. Anything I can do about this?
Using boot-cljs
recompilation times are significantly slower than using lein-cljsbuild
. With a project using boot-cljx
with 100 files it takes 10-15s on my machine while the leiningen equivalent takes a couple second.
This issue is derived from #22 .
Which direction should I look at to eventually improve that? Note that the recompilation looks disk bound, CPU is pretty flat but disk busy.
Would it be possible to add a :main
option to boot-cljs as it's described in CLJS-851?
It seems that the ticket is somewhat in limbo and maybe it can be implemented in a generic way that makes it easier further down the road to add features like splitting the compiled JS into multiple modules (see shadow-build).
@micha is that something you think worth exploring for this project?
/cc @thheller A question about shadow-build: when using something like :depends-on #{:mod-1 :mod-2}
in a module named :mod-3
does that mean that the compilation output of :mod-1
& :mod-2
will be added to the compilation output of :mod-3
or is the dependency information only required for proper compilation?
Recent versions of the ClojureScript compiler add support for a main option that is roughly equivalent to .cljs.edn
.
When specified as part of :compiler-options
the .cljs.edn
handling should be skipped.
As far as I understood --unified
splits up all sources into separate files and then uses Google Closure to load in the parts of the system. I think the name indicates the opposite which can be misleading.
Are there other reasons for the --unified
naming I'm not aware of?
Hi,
I wanted to try out boot(-cljs) because I was so frustrated with leiningen lately, but I can't get it working with om.
The generated main.js:
goog.addDependency("base.js", ['goog'], []);
goog.addDependency("../cljs/core.js", ['cljs.core'], ['goog.string', 'goog.object', 'goog.string.StringBuffer', 'goog.array']);
goog.addDependency("../clojure/string.js", ['clojure.string'], ['goog.string', 'cljs.core', 'goog.string.StringBuffer']);
goog.addDependency("../adzerk/boot_reload/reload.js", ['adzerk.boot_reload.reload'], ['goog.net.jsloader', 'goog.Uri', 'cljs.core', 'goog.async.DeferredList', 'clojure.string']);
goog.addDependency("../clojure/browser/event.js", ['clojure.browser.event'], ['cljs.core', 'goog.events.EventTarget', 'goog.events.EventType', 'goog.events']);
goog.addDependency("../clojure/browser/net.js", ['clojure.browser.net'], ['goog.net.xpc.CfgFields', 'goog.net.XhrIo', 'goog.json', 'goog.Uri', 'cljs.core', 'goog.net.EventType', 'goog.net.xpc.CrossPageChannel', 'clojure.browser.event']);
goog.addDependency("../adzerk/boot_reload/websocket.js", ['adzerk.boot_reload.websocket'], ['cljs.core', 'clojure.browser.net', 'goog.net.WebSocket', 'clojure.browser.event']);
goog.addDependency("../cljs/reader.js", ['cljs.reader'], ['goog.string', 'cljs.core', 'goog.string.StringBuffer']);
goog.addDependency("../adzerk/boot_reload/client.js", ['adzerk.boot_reload.client'], ['adzerk.boot_reload.reload', 'goog.net.jsloader', 'cljs.core', 'adzerk.boot_reload.websocket', 'clojure.browser.net', 'cljs.reader', 'clojure.browser.event']);
goog.addDependency("../adzerk/boot_reload.js", ['adzerk.boot_reload'], ['cljs.core', 'adzerk.boot_reload.client']);
goog.addDependency("../cljsjs/development/react.inc.js", ['cljsjs.react'], []);
goog.addDependency("../om/dom.js", ['om.dom'], ['cljs.core', 'goog.object', 'cljsjs.react']);
goog.addDependency("../om/core.js", ['om.core'], ['goog.dom', 'cljs.core', 'om.dom', 'cljsjs.react', 'goog.ui.IdGenerator']);
goog.addDependency("../app.js", ['app'], ['cljs.core', 'om.dom', 'om.core']);
This results in ReferenceError: Can't find variable: goog
. Am I missing something? Any help appreciated! 👍
This is the next issue blocking boot-cljs on Windows (after 109 in the boot project). PRs coming soon.
I think "0.0-2629-8" introduced a bug which emits "#!/usr/bin/env node" even for non-node artifacts.
I need to build a browser and a node version. With the recent addition of multiple builds I can build 2 files now, but they seem (?) to must share the same compiler settings.
For example, these are my tasks configs:
(cljs
:optimizations :advanced
:pretty-print false
:output-to "app.js")
(cljs
:target :nodejs
:optimizations :simple
:output-to "app.node.js")
How can I create two artifacts from the same source with different compiler settings?
Note: In Leiningen I had different source dirs (e.g. cljs-browser, cljs-server) to differentiate the source files.
The complete build.boot is at https://github.com/startupflock/frontend/blob/master/build.boot
The order of the CLJS namespaces that are goog.require()
appear in random, changing order, which interferes with things that track file changes like adzerk/boot-reload
.
The CLJS compiler has more options than the cljs
task in this project.
There should be a way to pass arbitrary options to the compiler
(I assume we don't want to add all of them as task options).
https://github.com/clojure/clojurescript/wiki/Compiler-Options
When a project defines a main.cljs
file any attempt to compile will trigger a Assert failed: Circular dependency detected [main]
error.
It looks like this is because boot-cljs
generates a main.cljs
file which requires project's main
namespace.
The problem is if I put some compiler options in my cljs task (in build.boot
), and have few .cljs.edn
files, and one of them overrides some option, then other .cljs.edn
files will have this option overriden to new value. I.e. if I have {:target :nodejs}
for one file, I have to specify {:target nil}
for another file explicitly. I don't think that was intended.
Follow-up on some discussion in #hoplon yesterday night.
Currently when using --unified
that will recognize the path to main.js
and load additional files based on this information. This is useful behaviour when using a Figwheel-like workflow, as only small portions of the code will be reloaded. When you serve assets as a route in Compojure though ((resources "/assets" {:root "public"})
) the modification of the paths stops working as the system can't correctly identify the main.js
file anymore.
I think it would be useful to support that usecase by allowing an optional argument to --unified
.
Perhaps a simple vector creating a mapping between a route and a directory within the target dir could work: ["/assets" "public"]
. This way when boot-clis
would encounter a <script>
starting with /assets
i.e. /assets/js/main.js
it could determine that this references public/js/main.js
in the target directory. With this knowledge all other paths could be determined.
This would also have to work with index.html
being in public
as well and only referencing js/main.js
but I assume that's doable.
Keep in mind that this optional argument would be fully backwards compatible and solve a very real usecase for people serving their assets through Compojure in development.
If that would be a feature you'd be interested in I'll try to come up with a pull request.
In the future maybe it'd make sense to move some of that html-munging stuff into separate tasks. That way you could also create tasks that change the paths from your local assets to CDN hosted ones.
Hi,
I want to write tests using clojurescript.test and run them using boot, however I am unable to find any info to do so. Could you please help ?
Thanks,
Murtaza
The CLJS compiler environment contains the dependency info about all of the JS files that other tasks will need. We should add the :dependency-order
key to those TmpFile
objects.
Hey, I recently started a new ClojureScript project using boot-cljs. Everything worked fine, except that I noticed that when I compiled with the :optimizations :advanced
mode of the closure compiler the main.js
file that came out clobbered my global namespace.
I was able to find the :output-wrapper parameter of the clojurescript compiler, and turning it on in my build.boot
file fixed the issue. However, my understanding is that with the advanced compilation options, this should be turned on by default.
I've included my build.boot
file below, in case it helps. Very much vanilla stuff though. The only change between the old and new versions is the :compiler-options
on the last line of the new one.
; old build.boot
(set-env!
:source-paths #{"src"}
:dependencies '[[adzerk/boot-cljs "0.0-2814-3" :scope "test"]
[adzerk/boot-cljs-repl "0.1.9" :scope "test"]
[adzerk/boot-reload "0.2.6" :scope "test"]
[reagent "0.5.0" :exclusions [cljsjs/react]]])
(require
'[adzerk.boot-cljs :refer [cljs]]
'[adzerk.boot-cljs-repl :refer [cljs-repl start-repl]]
'[adzerk.boot-reload :refer [reload]])
(deftask dev
"Watch/compile clojurescript files in development"
[]
(comp
(watch)
(cljs-repl)
(cljs :source-map true
:optimizations :none)))
(deftask prod
"Compile clojurescript files for production"
[]
(comp
(cljs :optimizations :advanced)))
; build.boot
(set-env!
:source-paths #{"src"}
:dependencies '[[adzerk/boot-cljs "0.0-2814-3" :scope "test"]
[adzerk/boot-cljs-repl "0.1.9" :scope "test"]
[adzerk/boot-reload "0.2.6" :scope "test"]
[reagent "0.5.0" :exclusions [cljsjs/react]]])
(require
'[adzerk.boot-cljs :refer [cljs]]
'[adzerk.boot-cljs-repl :refer [cljs-repl start-repl]]
'[adzerk.boot-reload :refer [reload]])
(deftask dev
"Watch/compile clojurescript files in development"
[]
(comp
(watch)
(cljs-repl)
(cljs :source-map true
:optimizations :none)))
(deftask prod
"Compile clojurescript files for production"
[]
(comp
(cljs :optimizations :advanced
:compiler-options {:output-wrapper :true}))) ; added the compiler options clause
README currently specifies that preamble, etc .. must be located in hoplon/include/
folder but it doesn't appear to be the case anymore? Maybe this should be removed to reduce potential confusion.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.