Fork me on GitHub

how can I play an mp3 with a button click in cljs?


i'm trying to interact with the Audio object ... i don't know how to initialize it, but theoretically there should be a browser default one i could invoke with a constructor (?)


If it's just a static MP3 file that your web server can serve to your web page, you can just use the <audio> tag. Then, the button to play the file would the, well, Play button:


If it's something more complicated, you need to give some details for a correct answer because WebAudio is "fun" at some places.


hey all I have started of on a new cljs project and I looked at the prod bundle which came to around 3.1Mb


is that normal ? the app in itself is not that big. If I had built this in plain React and ecosystem it won't be this big.


or is there any best practices I need to adhere to get the best out of closure compiler, I am hoping its a missing config or something small like that but I searched through google and couldn't find anything too different from the current project setup so I am a bit lost here. any help would be great. Thanks in advnace


Hi @varen90, which tool do you use to build? Are you using advanced optimization? What are your dependencies?


lein-cljstools and yes we use advanced optimizations


Hm I’m not familiar with lein and cljstools. 3mb looks a bit high, as if something is wrong. My only suggestion would be to browse the compiled bundle and see if there’s something there you don’t expect in terms of dependencies.


I use shadow-cljs and my main module was around 3mb too, but the culprit was Vega - it weighs in at around 1mb of dependencies.


Plus some other JS libraries like React-bootstrap


ah okay - how hard is it to migrate to shadow-cljs ?


oh yeah we use React-bootstrap


are u saying its not getting tree shaken properly?


It supports Leiningen so hopefully not too hard - I’d ask in #shadow-cljs for details.


I don’t think any tool can successfully free-shake JS stuff. For React-bootstrap, I used the “bundle” import instead of the “detailed” ones, which was an issue. Ended up just removing it after too many issues and too little value.


(Typing this on mobile so can’t provide links or details, sorry)


shadow-cljs is definitely the state of the art in build tools, and it has a nice report so you can see why your build is large. But if you use cljsjs you might have to do some legwork first.

👍 4

no worries, thanks for your help


shadow-cljs can also generate a build report that says what exactly took that amount of space:


Hi all. Going through a reagent/material-ui example. I can't get my head around what the caret is being used for here: (defn custom-styles [^js/Mui.Theme theme] .. Full example is here:


I've looked at a few js interop docs but couldn't find this.


^js/Mui.Theme theme that is a type hint. used for externs inference. it basically tells the compiler that this is a JS value and externs are added so that :advanced compilation doesn't rename it


theme is an instance of Mui.Theme class (which is made up in this case but that doesn't really matter much). the important bit is the ^js


Ahh.. thank you very much @thheller. All clear now. Much appreciated.


Hi - does anyone have an example of how I cat get an AST using self-hosted clojurescript? I'm struggling with how to set up the analyzer / compiler state / other parameters. I'm after the full AST like I can get in Clojure:

Binita Bharati11:01:47

How can I use jquery within cljs alongside shadow-cljs as the build tool ? jquery is residing in CDN. Thanks.


or you can just use the provided global via (js/jQuery "#foo"). then you don't need to tell shadow-cljs about jquery at all

Binita Bharati11:01:58

Thank you ! I tried the second option that is directly accessing (js/jQuery "#foo"). It works.


What are everyone's favorite resources for onboarding a JavaScript programmer on a ClojureScript project?


I just noticed that (cljs.reader/read-string "#(+ 3 %)") throws an exception whereas (read-string "#(+ 3 %)") works in clojure. Is there a way I can get this to work in cljs ?


cljs.reader is pure edn reader, it only reads edn data. the matching clojure variant would be clojure.edn/read-string


if you want read-string with full code capibilities you are entering self-hosted CLJS territory ... which is ... complicated.


ah OK interesting, thanks :thumbsup:


@thomas.ormezzano fwiw, edamame can do this:

$ clj -Sdeps '{:deps {org.clojure/clojurescript {:mvn/version "1.10.520"} borkdude/edamame {:mvn/version "0.0.10"}}}' -m cljs.main -re node
ClojureScript 1.10.520
cljs.user=> (require '[edamame.core :as edamame])
cljs.user=> (edamame/parse-string "#(+ 3 %)" {:all :true})
(fn* [%1] (+ 3 %1))


oh cool cheers 🙂


if you need actual evaluation instead of just parsing, you can use sci. see example in channel


for a while I've been getting:

$ clj -Sdeps '{:deps {org.clojure/clojurescript {:mvn/version "1.10.597"}}}' -m cljs.main -re node -e "(require '[sci.impl.interpreter :as sci])"
Unexpected error compiling at (<cljs repl>:1:1).
Not supported: class cljs.repl$init_wrap_fn
in although the project works fine when compiled (the tests run using a compiled version using cljs-test-runner) plk also works fine:
$ plk -e "(require '[sci.impl.interpreter :as sci]) (sci/eval-string \"(+ 1 2 3)\")"
Any hints what this could be?


with an older version of CLJS it also seems to work:

$ clj -Sdeps '{:deps {org.clojure/clojurescript {:mvn/version "1.10.329"}}}' -m cljs.main -re node -e "(require '[sci.impl.interpreter :as sci]) (sci/eval-string \"(+ 1 2 3)\")"


it seems to be related to writing something to transit: [cljs.analyzer$write_analysis_cache invoke "analyzer.cljc" 4593]


Got it. Continuing in #cljs-dev


Hi everyone 🙂 I want to share a library that I just published that helps you write modern React components with CLJS (yet another!). I started on a CLJS/RN project recently and felt that the various frameworks libraries out there didn’t try hard enough to get out of my way - surely it’s a matter of preference, but I really just wanted to define components using defn instead of some DSL or helper. I left state management out of scope, and I think ended up with a nice API that achieves the goal with strong extensibility. Broadcasting here because I’m happy with it and hope someone out there finds it useful 😁 Feedback welcome! Link below

👏 12

have you looked at uix[1]? that was my pick for my current project and I’ve been very satisfied so far. nice job @U0FR82FU1 [1]


Hey, no I actually don't remember seeing that. It looks really impressive! As an aside looking thru the docs, one thing I think rct gets right is that you can render templates with native components in the same way you do with CLJS components - driving rendering with protocols rather that tag-based template parsing lets you avoid the :> tag that uix and reagent use for interop. Perhaps I over-indexed on these ergonomic points in building a new lib - uix has a long tail of solid features, glad it's working well for you!

Eric Ihli16:01:34

I just expected something to work after reading and don't understand why it doesn't. Can anyone shed light?

(ns config)

(def ^:dynamic *flavor* :free)
  (:require config

(defn init []
  (binding [config/*flavor* :pro]
    (print config/*flavor*)           ;; pro... all good
(ns example.core
  (:require config))
(defn init []
  (print config/*flavor*)             ;; free... unexpected

Matti Uusitalo18:01:58

Shouldn't those requires be lists?

Eric Ihli16:01:27

For context and to know if there's a totally separate way I should be doing this: I ran into this while trying to figure out a way to have a single codebase for multiple versions of an app. I'm building with shadow-cljs for react native. So I was thinking I'd just point to different init-fn s in the config. For the dev/free version I'd point to and for the release/free version Those entry-points would bind some globals that I could then branch from in the app. I first tried using an atom to hold a map of config values. That worked fine, but what's the point of an atom there? I don't think I need "uncoordinated synchronous access to a single identity". I'm trying to use the right tool for the right job and understand the why's behind "right".

Eric Ihli17:01:40

Hm. It expands like this.

example.core> (macroexpand '(binding          [config/*flavor* :pro] (example.core/init)))

 (set! config/*flavor* *flavor*-temp-val__39543)
  (finally (set! config/*flavor* *flavor*-orig-val__39542))))
When I replace the binding call with some manual set!, it works as expected.


probably not the problem but example.core should not get things from config without requiring it

Eric Ihli16:01:10

Aye. Typo in Slack, not the code.


I'm struggling to debug these transit handlers: (for

(println "printing zdt" (t/in (t/midnight (t/date)) (t/zone)))
(println "type"  (type (t/in (t/midnight (t/date)) (t/zone))))
(println "transit zdt" (time-literals-transit/->transit (t/in (t/midnight (t/date)) (t/zone))))

;;printing zdt #time/zoned-date-time "2020-01-24T00:00-05:00[America/New_York]"
;;type #object[ZonedDateTime]
;;transit zdt ["~#offset-date-time","2020-01-24T00:00-05:00[America/New_York]"]
Things work fine on the clojure side but zoned date times are being written as offset date times on cljs. Anyone see an obvious errors in the gist? Edit: nevermind, I think it's an issue related to an issue in JS joda where OffsetDateTimes are just ZonedDateTimes (


Any reason why the REPL I'm using by following this guide is painfully slow?


Slow to start or slow to run code once it's up?