This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2017-01-30
Channels
- # bangalore-clj (1)
- # beginners (104)
- # boot (207)
- # cider (173)
- # cljs-dev (157)
- # cljsjs (1)
- # cljsrn (51)
- # clojure (196)
- # clojure-berlin (1)
- # clojure-chicago (1)
- # clojure-italy (4)
- # clojure-new-zealand (1)
- # clojure-nl (1)
- # clojure-russia (28)
- # clojure-spec (17)
- # clojure-uk (73)
- # clojured (13)
- # clojurescript (110)
- # core-async (4)
- # datascript (25)
- # datomic (92)
- # editors (1)
- # emacs (157)
- # events (4)
- # hoplon (16)
- # klipse (74)
- # lein-figwheel (10)
- # leiningen (2)
- # lumo (13)
- # off-topic (78)
- # om (3)
- # om-next (3)
- # onyx (14)
- # protorepl (1)
- # re-frame (17)
- # reagent (23)
- # remote-jobs (1)
- # ring-swagger (33)
- # schema (2)
- # slack-help (3)
- # spacemacs (7)
- # testing (1)
- # yada (7)
hey guys, I have CLJS single page app and using boot. I have API endpoint I hit and it’s defined like this
(def API_URL “)
. How do I define it differently for the production? My boot file looks like this (deftask build []
(comp (speak)
(cljs)))
(deftask production []
(task-options! cljs {:optimizations :advanced})
identity)
you could to:
(deftask build []
(comp (speak)
(cljs)))
(deftask production []
(task-options! cljs {:optimizations :advanced})
(build))
Yeah, but can I specify different API_URL
for production?
@grounded_sage CLJ and CLJS in boot use the same JVM, but likely different pods
@podviaznikov oh ok I did not notice that var above, so probably you need some dynamic var magic
(def ^:dynamic *api_url* ")
(deftask build []
(comp (speak)
(cljs)))
(deftask production []
(binding [*api-url* something]
(task-options! cljs {:optimizations :advanced})
(build)))
@grounded_sage it's not possible (yet) to actually share an atom across pods, but you can share for instance a java.util.concurrent.ConcurrentHashMap
@podviaznikov if you want to keep things this way, but there are many ways to handle it, you can make a let
inside each task, dev
and production
, or pass a parameter
tbh :dynamic
is the solution I like less
@micha so best thing to do would be to use enduro to put it into a file. Is there a way to put it in at the end of Clojure compilation and pull it back out at start of CLJS compilation. Just thinking that writing every change to disk will be slow.
For reference it's got to do with this implementation: https://github.com/GroundedSage/VeganBN-website/blob/master/src/clj/vbn/styler.clj
@grounded_sage can you describe...oh ok
i don't know how thread-safe writing to system properties is, but i imagine it would be easy to use some locking or whatever
Generating atomic css classes. So the issue I have is that I generate the styles and corresponding classes. During CLJ it renders Rum to static HTML with the Class names. But when it renders the client side Rum it starts fresh with a new atom and creates different class names. Due to the compilation difference I end up with a miss match of class names on html elements client side. cc @micha
@richiardiandrea thank you for the tips
@podviaznikov I am kind of afraid to show this to people 🙂 but in lambone
I use multi-methods for that, and the concept of "flavor", which is a string I pass from the command line: https://github.com/Lambda-X/lambone/blob/master/resources/leiningen/new/lambone/common/build.boot#L101
@grounded_sage so you need to share a map between clj and cljs?
Yea pretty much.
i wanted to go the other way, like the inverse of what you're doing, but it would work the same
like i wanted to be able to do this in my hoplon app:
(style :href (cache-bust "css/main.css") :rel "stylesheet")
but then a boot task (in CLJ land) would know that it has to rename that file and use the precomputed hash
Should I use this library? https://github.com/weavejester/environ or is it easy to just set it with some interop or something?
Cool cool. That's what I thought. Felt like a library would be overkill.
Thanks. I'll give it a crack sometime today and see if it resolves the issue I am having.
hi, is it possible to have a run
task which uses two different pods ( one for clj, and one for cljs ) to run a clojure and clojurescript application ?
Hmm, do we have any examples of boot-in-pod, for testing?
boot.core/boot
is not available inside pods but is there some other way to run boot inside tests?
@juhoteperi you can call boot.App/runBoot
from anywhere
Hmm, but that one needs the tasks as command like string args
Only things boot.core/boot
really do are to create fileset (and setup fileset sync, which I don't need) and run the task pipeline with the fileset
So I think I should only need a way to create fileset, and run it with my pipeline function
For testing, it might make sense to completely mock the fileset
Then I don't need to include the test files in application classpath at all
boot.tmpdir
is available from pod so should be doable
@juhoteperi there is a function in boot.core for creating a new fileset
Yep, I'm just re-creating it for my usecase
Eh, I can't require the task namespaces as those require boot.core
also, the global env
is a bit impractical here
should make this easier
Also maybe this can be helpful? https://github.com/boot-clj/boot/blob/master/boot/core/test/boot/task/built_in_test.clj
also I'm not sure how far I can get with testing boot-cljs as Cljs does use classpath
@richiardiandrea That would probably work, but I was hoping I could just call boot
in normal deftest
and check the results
It'll make the testing easier if I can mock away all the state (deps, classpath, watch task...)
I had the same problem I think while doing it and decided to take this other way together with micha 😀
Definitely
Hmm, I should be even able to "mock" or control classpath with Thread.setContextClassLoader
I just wonder if new threads inherit current context class loader
> A thread's context class loader is, by default, set to the context class loader of the thread's parent.
should work...
but future
& co use existing thread pool so those won't inherit my context class loader
Yeah @juhoteperi unless you hook a ThreadFactory
I guess?
@lxsameer less4clj should be quite simple: https://github.com/Deraen/less4clj/blob/master/boot-less/src/deraen/boot_less.clj#L64-L67, a pod with one extra dependency and one with-eval-in
hmmm, I want to have a task called run
, Invoking it should run several tasks under pod A and several other tasks under pod B
(def pod-a (future (make-pod ....)))
(def pod-b (future (make-pod ....)))
(deftask run
....
(with-eval-in @a (cljs-tasks))
(with-eval-in @b (clj-tasks)))
you can create a pod with variouus maven dependencies, and then you can eval expressions in that pod
@micha I'm trying to fire up both clj and cljs environment in the same task, and since I'm using Sente, and it has some weird bug with reloading and clojure.tools.namespace.repl
so I'm looking for a solution to run them side by side but without any effect to each other
Now I have Agent/soloExecutor
set so that future
sees the changed context class loader, but now I fear that pods might not inherit context class loader 😄
I'm using tools.namespace fork for now
@juhoteperi do you do the same thing as I'm doing ? ( I mean clj and cljs together )
You could try adding these deps to the project, though I can't really recommend using this:
;; FIXME: Need to depend on both, else some task or such
;; might add old org.clojure/tools.namespace 0.2 version to a pod which contains
;; clj files instead of cljc and those overwrite the new files.
;; Fork is latter so it will overwrite files from original.
[org.clojure/tools.namespace "0.3.0-alpha3"]
[metosin.forks/tools.namespace "0.3.0-20160926.120815-2"]
I don't think I have any public projects using this
But except for those deps, the projects are very similar to https://github.com/Deraen/saapas/blob/master/build.boot#L64-L81
Exception in thread "main" java.lang.NoClassDefFoundError: clout/core/CompiledRoute
Well, I got quite near of mocking boot, fileset & classpath, but pods inherit App.class.getClassLoader()
instead of context classloader and I can't find a way to override classpath for pods created by tasks
@escherize Yes, that looks like something that might be caused by AOT compilation
Compojure probably generates some code with macros that refers to that class and AOT compilation doesn't properly compile that namespace, or doesn't just include the compiled class files for some reason
Wow @juhoteperi that's a hack 🙂 ^
I wonder if your hack should replace the current boot.test
, it probably should, and we could try if it works with that file I pasted above
Yeah, mocking fileset is easy enough but all that shared state in Clojure core and Boot makes that implementation really compilcated
@richiardiandrea It doesn't work yet, at least for Cljs, which uses classpath
got it, just spreading ideas 😄 It looks interesting for sure
my approach was no towards mocking stuff, but it is more cumbersome in a way...
boot’s killing me again. my task is trying to read a string from an edn file in the fileset, and use it as the :dir param to the target task. I can’t get the string unless i use something like with-pre-wrap, but if I put the target task inside of that nothing happens. so i tried this:
(let [target-dir (atom "target")] (comp (boot/with-pre-wrap [fileset] ... get dir string from edn file ... (reset! target-dir dir) fileset) (builtin/target :dir #{@target-dir} :no-clean (or no-clean false))))
but it doesn’t take. @target-dir ends up as “target”, not the dir string. how can I make this work? thx.
(with-pre-wrap)
needs to be wraped in a fn doesn't it? @mobileink
@pesterhazy : i don’t think so, that pattern works in my other tasks...
@mobileink Not possible (at least cleanly), task options are set in a step before any handler core (code inside pre-wrap
etc is run)
But it is possible to create new target
task inside task that reads the edn file, in this case, the task will lose it's state (e.g. with cljs, the compiler state) but with target
task this doesn't matter
what do you mean by “create new target task inside task that reads the edn file”? i tried to invoke builtin/target inside of with-pre-wrap, but nothing got written.
(defn read-edn-and-run-task []
(fn middleware [next-handler]
(fn handler [fileset]
(let [{:keys [target-path]} (...read-edn fileset...)
target-middleware (target :target target-path)
target-handler (target-middleware next-handler)]
(target-handler fileset)))))
target
returns new middleware with the given option, target-middleware
handler which can be called with a fileset and when finished, will call next-handler
(what ever is after read-edn-and-run-task
in the pipeline)
My recommendation is to not use pre/post-wrap
, using middleware pattern directly makes it much easier to see what really happens
stack overflow. how do I use that kind of thing inside a deftask? it needs to be able to take params.
(defn read-edn-and-run-task [] (fn middleware [next-handler] (fn handler [fileset] (let [boot-config-edn-files (->> (boot/input-files fileset) (boot/by-name [boot-config-edn])) boot-config-edn-f (condp = (count boot-config-edn-files) 0 (do (util/info (str "Creating " boot-config-edn "\n")) (io/file boot-config-edn)) ;; this creates a java.io.File 1 (first boot-config-edn-files) ;; this is a boot.tmpdir.TmpFile (throw (Exception. (str "only one bootconfig.edn file allowed, found " (count boot-config-edn-files))))) boot-config-edn-map (if (instance? boot.tmpdir.TmpFile boot-config-edn-f) (-> (boot/tmp-file boot-config-edn-f) slurp read-string) {}) dir (str "target/" (-> boot-config-edn-map :module :name)) target-middleware (target :dir dir) target-handler (target-middleware next-handler)] (target-handler fileset))))) (boot/deftask target "target, using module name" [C no-clean bool "Don't clean target before writing project files" d dir DIR str "target dir" s servlet bool "building as servlet" v verbose bool "verbose"] (read-edn-and-run-task))
boot-config-edn-f (condp = (count boot-config-edn-files) 0 (throw (Exception. (str boot-config-edn " file not found"))) 1 (first boot-config-edn-files) ;; this is a boot.tmpdir.TmpFile (throw (Exception. (str "only one bootconfig.edn file allowed, found " (count boot-config-edn-files))))) boot-config-edn-map (-> (boot/tmp-file boot-config-edn-f) slurp read-string)
d’oh! it helps to call (builtin/target :dir dir) when you have a task also named target. now it works, thanks!
Wohoo, Boot-cljs now uses real class names for de-serialized exceptions from Cljs: https://github.com/boot-clj/boot-cljs/commit/1e840fabf63ec5b98f3caf67325e003fb766410c
@juhoteperi if you push a SNAPSHOT I'll try it right away against boot-figreload
as well 😉
I am about to update it to 0.5.9
, btw good job ^
@richiardiandrea Snapshot deployed
awesome thanks!
Hmm, shouldn't happen
let me clear the .m2
folder
isn't that fn missing a param vector? @richiardiandrea
yep, I am triggering the error
Yeah, the problem is that the file path in exception message should be shorter
https://github.com/boot-clj/boot-figreload/blob/master/src/powerlaces/boot_figreload/figwheel.clj#L137 btw. this bit is no longer necessary
thanks, I am going to remove it and see
Okay, I presume that the problem is in ex-parsing/parse-inspected-exception
so @juhoteperi the whole thing is not necessary anymore?
@richiardiandrea exceptions use real classes instead of proxy, so there won't be those hideous class names anymore
oh ok, that was a big deal when I first implemented it
But the problem with file path is probably that Figwheel logic selects the original :file
property from some exception in cause stack, instead of the one that is processes by Boot-cljs
trying again, I got rid of that regex
https://github.com/bhauman/lein-figwheel/blob/master/sidecar/src/figwheel_sidecar/cljs_utils/exception_parsing.clj#L80 this should select ex-data from the first exception that has tag analysis-error, and that should be the ex-info created by boot-cljs with correct filepath
hum..it went even worse
hmm, send-visual!
uses the serialized exception directly?
yes but I had to adapt it
I am debugging
I think figwheel resumes that :class
property has a real Class object
yes exactly
that is why I needed to resolve the string there
you can take store (.getName (class e))
on serialization and resolve that
so I used to do it for (re-find #"^adzerk.boot_cljs.util.proxy\$(.+)\$.+")
now I need to do it all the time basically right?
It did it for every class before also
Or no
It should work with just string names: https://github.com/bhauman/lein-figwheel/blob/master/sidecar/src/figwheel_sidecar/cljs_utils/exception_parsing.clj#L289
uhm...ok need to check that part again, thanks for your help for now
what I receive is:
{:exception {:class "clojure.lang.ExceptionInfo", :message "Parameter declaration \".info\" should be a vector at line 10, column 1 in file src/figreload_demo/core.cljs\n", :data {:file "src/figreload_demo/core.cljs", :line 10, :column 1, :tag :cljs/analysis-error, :from :boot-cljs, :boot.util/omit-stacktrace? true}, :cause ...}
That looks correct
ok cool, so I'll continue from here, tnx
Hi guys, company (Runnable) starting to offer free service for few OS projects. We do staging env per commit. I set it up for perun. I can’t come up with use case for boot, but still wanted to check with you. If you think Runnable can be useful for boot - let me know
so @juhoteperi basically the problem is that the :display-ex-data
key is generated recursively: https://github.com/bhauman/lein-figwheel/blob/5e8ea217f9243e50e47e688b1100b78094e4f4af/sidecar/src/figwheel_sidecar/cljs_utils/exception_parsing.clj#L44
and except for the first one we don't normalize paths in our stack traces
shall we do it on our end (probably yes, but I have to do in boot-cljs
)
I'll leave it as it is for now and push a new version of boot-figreload
SNAPSHOT pushed
^ http://boot-clj.github.io notifications are probably unnecessary
my bad
hm, looks like we have an organization webhook
do we like the notifications for the other boot/* projects?
i'm kind of for no notifications
yeah, this channel is so active that it might be best to just turn of notications completely
hey bootsters! i'll bet a lot of you think of boot as a build system. not so! it's JCL (Job Control Language), done right! https://clojurians.slack.com/archives/google-cloud/p1485816735000754