Fork me on GitHub
#clojurescript
<
2016-04-12
>
vincentdm00:04:47

Hi all! Can anyone point me to a solution to randomize the filename of my output .js build? In webpack you have a wonderful plugin to clone your HTML file and insert the reference to the randomized build file. This enables you to let clients cache the JS file, while keeping the html uncached so they see the reference to the new file as soon as it is published. I'm using Leiningen with cljsbuild.

vincentdm00:04:32

I tried to insert :output-to (str "resources/public/js/app_nl_" (System/currentTimeMillis) ".js") in my :compiler options, but that led to an error: 'java.lang.IllegalArgumentException: No implementation of method: :as-file of protocol'

vincentdm00:04:24

Ok, turns out my approach does work, I just needed to add a ~ in front of it, to prevent the Leiningen auto-quoting. So now I have to figure a way to add the randomized filename to my html. If anyone knows of an existing solution: still welcome!

xcthulhu02:04:03

You could set your file-name in leiningen/boot with defonce and pass it to Clojure with :jvm-opts [(str "-DjavascriptPayloadName=" +javascriptPayloadName+)] (or the equivalent in boot that I don't know off the top of my head)

xcthulhu02:04:06

Then do (System/getProperty "javascriptPayloadName") to recover the name in your Clojure, or use cprop if you want a wrapper: https://github.com/tolitius/cprop

magnars11:04:11

I am using cljs.build.api/build to build my cljs-project programatically. I know about :warning-handlers, but what about handling errors? It returns nil error or no, and throws no exceptions. Anyone know?

dnolen11:04:26

@magnars: we don’t attempt to catch exceptions as the compiler usually can’t recover

dnolen11:04:42

you can catch exceptions if you like - we could be more consistent internally about how this is done

dnolen11:04:50

more low hanging fruit for somebody with time to spare

magnars11:04:06

That makes sense - I just want to (System/exit 1) after a failed build tho.

magnars11:04:27

Right now my build server thinks everything is splendid. simple_smile

dnolen11:04:39

@magnars: so call that from your handler or catch an exception and do that?

dnolen11:04:15

you of course need to take care to wipe out the build if you do this

magnars11:04:17

I'm probably doing something wrong then, because cljs.build.api/build doesn't throw any exceptions.

dnolen11:04:24

since it will most definitely be corrupted.

dnolen11:04:55

@magnars: I don’t recall that it swallows exceptions

magnars11:04:12

I get this printed out: ERROR: JSC_CONSTANT_REASSIGNED_VALUE_ERROR. constant navigator assigned a value more than once., but it returns nil with no exception.

dnolen11:04:47

@magnars: ah, that’s a Closure error that’s why

dnolen11:04:33

we don’t integrate with those - we could - Closure supports custom error handling if I recall

magnars11:04:11

ok, thanks for the info!

lwhorton18:04:28

what’s a good strategy for js interop where the offending js doesn’t return something (mutates passed-in value)?

lwhorton18:04:12

for example…

(let [mutated (js->clj (.someJsFn js-obj (clj->js some-state-arg)))]
  (merge some-state-arg mutated))

grav18:04:16

@lwhorton: I’d wrap it in a function that clones the object, then mutates it and returns it.

grav18:04:37

You’d need some form of deep clone. Maybe the library you’re using has one for that type?

lwhorton18:04:12

I’m just having trouble with step 1, i.e. if I hand the js function a (clj->js {}), I can’t capture the return value (there is none, it just mutates the map in place)… but I’ve lost reference to the map on the cljs side

lwhorton18:04:16

oohh, i see. I think I was just being silly.

lwhorton18:04:58

(let [mutated (clj->js some-state)]
  (do-mutation mutated)
  (js->clj mutated))

lwhorton18:04:00

simple as that

grav18:04:18

exactly simple_smile

grav18:04:24

(let [x (clj->js {:foo 42})]
  (set! (.-foo x) 43)
  (js->clj x :keywordize-keys true))

grav18:04:36

returns {:foo 43}

lwhorton18:04:39

i spent the last 20 minutes looking at atoms thinking that might be the answer

grav18:04:53

hehe, know the feeling simple_smile

darwin18:04:13

I have a string in a variable v and calling (int v) spits compiler warning "WARNING: cljs.core/bit-or, all arguments must be numbers, got [string number] instead"

darwin18:04:25

trying the same thing in planck, works without warnings, I tried to read the source code in cljs.core and I have no idea where is that warning coming from

mfikes18:04:59

@darwin: bit-or is a macro-function.

darwin18:04:49

what does it mean? it is a function which generates code like a macro would

darwin18:04:54

why it works sometimes and in my case gives a warning?

mfikes18:04:15

@darwin there are two places of code to read. The macro has ^::ana/numeric meta on it.

mfikes18:04:22

But, in short, it means you’d need to read the macro version if you are using it in operator position.

darwin18:04:08

ok, thanks for the pointers, so I should figure out why the macro version is not called in my code (or the other thing)

mfikes19:04:02

@darwin: Always emitting warnings has been a challenge with bootstrap ClojureScript and Planck. But, on the surface, this appears to be one of those functions that requires numeric input.

darwin19:04:26

I have been always using int function to coerce stuff into integers…

jr19:04:52

@darwin: the analyzer will only warn when it knows the type is not an integer

jr19:04:49

;; Will not warn
((fn [x] (int x)) "foo")

;; Warnings
(let [x "foo"] (int x))
(int "foo”)

darwin19:04:05

@jr: ok, thanks for the explanation

curtosis20:04:20

I'm trying to understand something about how macros work in cljs.... Looking at https://github.com/luxbock/bootstrap-cljs/blob/master/src/bootstrap_cljs/core.cljc, it generates a bunch of macros that create the cljs-friendly forms of the components, like (bootstrap/input ...).

curtosis20:04:55

What I don't get is what causes the #?(:clj ...) code to get executed at all doing a cljs compile?

curtosis20:04:10

well, yeah, but as I understand reader conditionals, anything inside a #?(:clj ...) form is only seen by the CLJ compiler, and NOT the CLJS compiler. is that not right?

lvh21:04:08

curtosis: that is correct

lvh21:04:24

curtosis: normally when you use macros in cljs code, the macros themselves are actually clojur

lvh21:04:42

that’s normally not a problem because stndard cljs relies on having the closure compiler anyway, so you already have a JVM around

jr21:04:09

@curtosis: the clojurescript compiler will read clj code as a first pass and intern the macros. That preps the compiler environment for cljs

curtosis21:04:57

ahhh... that makes sense operationally. it perhaps just doesn't map cleanly to the mental model of the reader conditional. ("I'm compiling CLJS; ignore these")

mfikes22:04:57

@curtosis: And, for completeness' sake, it's worth mentioning that the :cljs branch is followed for macro code in bootstrap ClojureScript.

curtosis22:04:09

@mfikes: ah, good. that one makes sense. good to know I'm not crazy, the history means it really is a little quirky!