Fork me on GitHub
orestis15:04:12 not sure if relevant, React seems to have switched to Closure compiler for compiling down to ES5


relevant for people who are militant about their dependencies (which is generally a good idea)


but not that meaningful for typical users prioritizing getting stuff done


it doesn’t look like they ship closure-y source so it’s not like we can treat it as non-external, right?


Not true, React is pretty Closure compatible


really all JS that doesn't do string based programming is already compatible


but lots of libraries do unnecessary dynamic stuff


so as long as people grab libraries willy nilly - then you're stuck w/ Webpack or whatever build mudball de jour


that said given how we've done things where we do have most of the stuff in place to DCE node_modules via Closure


so it doesn't matter if you use Webpack or whatever today


tomorrow you can use Closure


I haven't looked at the most recent React releases, but at some point React created bunch of methods and properties dynamically. Even if you don't use the methods from your own code, React uses ["foo"] when declaring them dynamically and .foo to refer to the same methods in other places, so externs are required to optimize React code. (Not sure if this is relevent for this discussion, just note about React being Closure compatible).


@juhoteperi yeah that was years ago at this point - I know that FB has been using Closure to optimize their own React usage for a couple of years now


I don't know if that forced them to solve that annoyance


but I'd be surprised


Yeah, the last related fixes to Cljsjs extern file where 3 and 2 years ago


But these problems weren't also very obvious to see, like 95% of Reagent tests passed and then a few test cases where broken due to these problems.

Roman Liutikov18:04:10

iirc, React team reached to Closure people at some point to get a couple of switches in the compiler that makes advanced mode less aggressive specifically for React


I think I addressed all the reported externs inference issues - let me know if I missed anything


if you all some low hanging fruit issues you'd like to see added to the next release let me know


3195, not now - 3086 approved


the others are too minor for now

👍 4

here are my current thoughts about the coming changes -


feedback welcome, it's pretty simple - and I have another project that more or less confirms that it works


I can’t quite tell exactly what the motivation is yet. it sounds like it would be really useful for people who want to consume their CLJS code in storybook, or use with react-native. is that close to the mark?

Oliver George05:04:02

I'd be interested to see a working example if you do find a way to use Storybook with CLJS code.


@lilactown it removes nearly all the steps (some error prone) for people who want to use some random lib


but more importantly it provides a portable way to create clojurescript libs that depend on node_modules


that's not really possible today because there's no standard way to do it


the state of the art for creating CLJS libs that use JS deps is CLJSJS


and that's also error prone, requires maintenance


I see. agreed about cljsjs


I didn’t understand anything in that gist to be about clojurescript libraries. the bulk of the content seems to be about a :bundle target? I’m not sure yet how that rolls into libs


I suspect this already works for shadow-cljs but shadow-cljs isn't the standard tool chain so it's not really much of a win - not portable

👍 8

@lilactown because we don't need to talk about anything else other than :bundle


:npm-deps already exists and works


it was always a la carte


i.e. doesn't directly imply Closure, :nodejs target avoids that


hmm. I guess maybe I’m out of my depth? I don’t understand yet the link between a :bundle target that (by the gist) > any tool that handles Node.js `require` can build ClojureScript - webpack, metro, etc. to the problem of libs that depend on node_modules or using some random lib. I’m looking at this from several perspectives: • I’m a ClojureScript library author whose most popular libs depend on node_modules. How does this effect my libraries? • I’m an application developer who uses many node_modules libs and uses many ClojureScript libraries that wrap node_modules. How does this effect my toolchain and dev experience?


perhaps, if I’m inferring right, it means that instead of: webpack creates a big ball of JS that then GCC needs a bunch of externs / must export to the global context… it would go the other way: we would emit a bundle of CLJS code with holes, that expects the node_modules deps to be require(…)able and then feed that into webpack so that it can resolve the requires to node_modules and have webpack emit our final bundle


I'm a ClojureScript library author whose most popular libs depend on node_modules. How does this effect my libraries? this category does not exist


I'm an application developer who uses many node_modules libs and uses many ClojureScript libraries that wrap node_modules. How does this effect my toolchain and dev experience? fewer steps, less boilerplate when working the standard compiler


@lilactown right but nothing I said talks about webpack specifically - in fact not interested in automating that part at all


users will start webpack, fastpack, metro or whatever


this is a good area for people to extend ClojureScript to make a shadow-cljs like experience + Figwheel or custom build setup or whatever


that makes sense!


there are aren't any portable ClojureScript libraries that depend on node_modules today that don't require a lot of manual project-specific non-reproducible steps


if there were people wouldn't still be going to CLJSJS


that’s very true. I’ve had to maintain a separate branch of for cljs/figwheel-main, since the main branch implicitly relies on some behavior in shadow-cljs. it makes me feel bad, but it’s what I use both at work and for hobbies so it makes sense to spend most of my time with that


right that's basically the worse case scenario


so this is about establishing a normal way to do this - shadow-cljs supporting the standard way along w/ it's own way shouldn't be hard


libraries authors shouldn't have to care which thing is going to build their thing


yeah, my case isn’t exactly related to node_modules but it’s a sort of second-order effect


I also think that paving the pathway for consuming CLJS code from any JS bundler is a really good idea when it comes to incremental adoption. I was lucky with the projects I’ve been on the last few years, because we were able to start greenfield with CLJS.


trying a bottom-up incremental adoption of CLJS is a harder sell, since there’s so much boiler plate and additional stuff outside the happy path to get it running in an existing project using webpack or rollup or whatever the bundler du jour is


looking at your project, I would say that's directly related to the node_modules problem 🙂


because you can't do it w/o shadow you have to describe a whole bunch of other steps


@lilactown w/ my proposal above the caveats about non-shadow tools just go away


the npm step is also not necessary


you can add src/deps.cljs - the root of your classpath with those deps declared


then anyone can install the required npm deps, it doesn't matter what tool they finally end up using


I’ll do that now!


I still need to maintain a separate branch, unfortunately, due to some differences between how shadow and vanilla cljs handle JS in-project. that’s what I meant by second-order effects.


don’t need to get into that now, not relevant and I don’t completely understand it myself


huh, like Closure style JS in the project?


with shadow-cljs, I can use ES6 import/export but it doesn’t work as well with Closure-style JS (for some reason I haven’t spent the time to diagnose). with cljs, I couldn’t get the same ES6 import/export and require syntax to work, so I used goog.provide


huh - ok - honestly if you need some JS and you want it to always work for ClojureScript writing plain old Google Closure JS is probably wise -, is worth studying if you want to make it slightly less tedious. especially if you're not writing a lot JS it's not worth it to complicate the build for people by writing higher level JS


thanks, I’ll try and take another look at it soon


yeah it’s very minimal - the only reason I did it was to try and get better interop with native classes


trying to create classes the ES5 way doesn’t quite have the same behavior when the browser actually has native classes, so my hope was that I could rely on GCC to compile down the helper fn to either ES5 or actually use real classes depending on what the user wants to emit


this way from my cljs code I can just spew:

 #js {:constructor (fn [this] (set! (.-state this) #js {:foo "bar"}))
      :render (fn [this] ,,,)}


@lilactown deps.cljs should be able to help you here too, but this feature is not under heavy usage - I haven't had a need myself - so I can't say more than we test basic stuff and that appears to work


gotcha. I’ll try and play with it over the weekend.


while I have your attention about this, would you ever consider a patch that added a form that emitted a class ? 😅


it's worth thinking about since that is a well known pain point - the problem is that you would need to transpile the generated JS again with Closure if we're going to maintain the nice fact that ClojureScript only generates ES3


people keep talking about generating higher level JS but I really see only tradeoffs and most of them not in favor


@lilactown, the beginning of this explains what you need to do

👍 4

:foreign-libs [{:file "helix/impl/class.js" :module-type :es6}] should theoretically work for you in your deps.cljs


I have reported issue for this some time ago and seems not resolved


if it doesn't - bug


yeah, a lot of higher level features have a relatively minimal impact on applications, but a considerable impact on project maintenance


from the perspective of a maintainer of CLJS, I mean


right, higher level features mean a more complicated pipeline, worse perf, etc.


(compiler perf, possibly runtime perf - ES3 is fast)


yep. tho it was interesting to see what people were talking about re: future async/await perf benefits but that’s even a whole other level of effort, since AFAICT it would require so much work to make the way that CLJS handles things like do work with the function-boundary behavior of async/await


class is one that really bites me since more and more browsers are supporting it natively, and so interoping with them becomes more of a pain point. it’s minimal in most application code, but the places you need it you need it and you can’t get away with an ES5 mock of a class


people keep talking about async/await perf but honestly I find such talk meh esp. in browser context


Node.js really isn't that interesting for server IMO if you're already doing Clojure anyway


so that's why not much has happened here - I just don't see much value


I think some work on codegen for core.async is all that it really needs - it's not that slow


@lilactown re: class I'm not against this if it's selective


i.e. if you use defclass we'll generate ES6 and do a second pass w/ Closure on that file


it doesn't sound like a particularly hard project (I already have a Closure transpile in ClojureScript) - if you want to take a look at this be my guest


it's definitely an interop gaping hole


I’ll create a ticket and try and find time to take a look


in the ticket mention we need 2 parts - defclass macro and compiler support

👍 4

it’s not an immediate need - my Closure JS workaround seems to work OK - but it would be really nice to delete that code from my projects


sure, but is something people have asked for years


now that we have easy single file transpile support I don't really see any issues


it does affect source mapping but that can be done as separate enhancement ticket