Fork me on GitHub
#clojurescript
<
2020-11-13
>
borkdude11:11:18

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

borkdude11:11:51

(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?

borkdude11:11:04

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

thheller11:11:20

(: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.

amorokh11:11:08

ah, great, thanks!

thisgeek15:11:48

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?

thisgeek16:11:09

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

cap10morgan17:11:33

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?

thheller17:11:53

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

thheller17:11:43

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.

thheller17:11:46

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.

cap10morgan17:11:47

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

cap10morgan17:11:05

I would have expected it to all be eliminated by DCE

cap10morgan17:11:11

since I'm not calling any of the fns yet

thheller17:11:23

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

thheller17:11:48

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

cap10morgan17:11:28

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

thheller17:11:42

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 https://shadow-cljs.github.io/docs/UsersGuide.html#_build_report

thheller17:11:36

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

thheller17:11:21

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

thheller17:11:56

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

cap10morgan17:11:32

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. 🙂

cap10morgan17:11:51

thanks for the insight, though. very useful.

thheller18:11:07

"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?

cap10morgan18:11:39

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

cap10morgan18:11:55

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

cap10morgan18:11:15

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

thheller18:11:10

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

dnolen18:11:17

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

dnolen18:11:39

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

dnolen18:11:08

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

dnolen18:11:24

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

dnolen18:11:32

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