Fork me on GitHub

With core.async, does one still need to load cljs.core.async.macros manually?


(ns repro
  (:require-macros [cljs.core.async.macros :refer [go alt!]])
  (:require [clojure.core.async :as async]))
Can one also write (async/alt! ...) now without requiring the macro namespace?


I'm asking for @amorokh but I'm also curious myself.


(:require [clojure.core.async :as async :refer (go alt!)]) is fine, as is async/alt!. no need for .macros unless you are on a really old version.


ah, great, thanks!


I have a clojurescript library filled with reagent components. Another project I work on uses plain old React, and it wants to consume those components. I figure, essentially, I have to find a compiler that has a target that knows how to make commonjs modules. At first I tried shadow-cljs to do that. It might have worked, but when rendering the components that I have imported I see a lot of this:

Objects are not valid as a React child (found: object with keys {children}). If you meant to render a collection of children, use an array instead.
So. two part question: 1. Am I barking up the wrong tree with shadow? Is there an alternative I should try? 2. If “no” to question 1, then (a shot in the dark here) do you have any leads what the problem might be?


No. I had not seen this document. I’ll check it out.


From the Closure compiler docs, it sounds like dead code elimination works at the function level (i.e. if you don't call a function, its definition will be eliminated from the final bundle). But in my own testing with CLJS (with tools-deps and target-bundle), it seems like it works at the namespace level. If I require a namespace (not even use it), that entire namespace and all code that it transitively requires gets included. Is that the expected behavior?


are you testing with :advanced optimizations? there are some exceptions that aren't removed by DCE but it does work at a function level


as far as CLJS is concerned requiring a namespace will pull in all of it and its dependencies. :advanced may move stuff between "namespaces" and delete unused stuff.


but for examples multimethods are never removed by DCE. so if you have code that has a defmulti and defmethod then that is never removed and all the code they call isn't either.


nope, just regular functions. just requiring a namespace is adding hundreds of KBs to my final advanced optimizations JS bundle


I would have expected it to all be eliminated by DCE


since I'm not calling any of the fns yet


hard to say. depends very much on what the code actually does.


DCE definitely does work and if the code is written with that in mind it will be removed entirely


Is there any way to get more insight into the decisions the closure compiler is making there and why?


it is kinda hard to debug or even tell what code is actually staying alive. in shadow-cljs there are build-reports which make this a whole lot easier but there is nothing comparable for :target :bundle


as far as the closure compiler there is no way I'm aware of to debug this in more detail


besides :pseudo-names true to actually even tell what any of the code even is of course 😛


it might be that you require some namespaces that require JS code (eg. react, react-dom). that won't be removed either.


yeah there is some of that, but it is closure-compatible so I've tried running it through the closure compiler too and the final bundle size didn't change. could be I just screwed that up somehow though. really hard to tell what closure is doing. 🙂


thanks for the insight, though. very useful.


"final bundle size didn't change" doesn't sound like you are using :advanced? or what are you comparing it too? :advanced will definitely make everything much much smaller even if it doesn't "remove" any code?


I am using advanced, in the before and after of that test.


advanced is much smaller than the other optimizations, to be sure


I'm just trying to figure out why I'm seeing this unexpected behaviour w/r/t DCE


yeah its kinda tough to tell why something isn't removed. requires a lot of digging through pseudo-named code to figure out and avoiding the pitfalls


@cap10morgan understanding and leveraging DCE in a precise way is a bit of black art


but if you're transitively depending on React or JS stuff, it's pretty much expected to balloon your bundle


you can't eliminate that stuff, and code that uses stuff that Google can't see isn't safe to eliminate


if you do some simple tests with pure ClojureScript code you'll see that pretty much what you would expect from DCE is true


because everything written in pure ClojureScript barring multimethods and specs (which mutate a global store) are free floating JS fns or JS types which can be understood by Closure