Fork me on GitHub

I'm very skeptical about the loading of AOT twice being slower, so not convinced unless you have measurements - otherwise what is the problem


Google Closure did this and it seems mostly a net benefit


what benefit? closure constantly breaks when people use it together with datomic on the classpath due to guava for example? it is also a different story since that is all java based you can just replace one .class with another. with Clojure AOT once it starts loading one AOT class it'll load only AOT classes. so just putting a newer tools.json version on the classpath (that does not contain any .class) does nothing, just confuse the user why they don't see the new version being used although it should be


"AOT twice being slower" I mean that the code will load the mranderson-styled renamed tools.reader AOT variant and then the non-AOT require variant requested by shadow-cljs. yes, loading the AOT variant is much faster but still not free. so give it a 20% overhead.


right now it is just loading the regular cljs-bundled AOT variant, so that is fast which is great. at the downside that you cannot easily replace it with a newer version. which is not that big of a deal but does end up confusing people sometimes.


but since we are talking about milliseconds here that is not a big deal performance wise. I'm more concerned with the possible dependency confusion.


these are minor concerns but I still believe that AOT by default is not what any CLJ/CLJS libraries should be doing. it does create confusing errors that aren't hard to fix but very hard to identify properly (eg., note this is an example of the closure "problem" mentioned above. not related to AOT cljs)


I think no library should contain AOT-es classes from its transitive dependencies


@borkdude i do not believe that is even possible if you AOT


This is definitely does work. Clojure loads code per-class, and source files can load AOT and vice versa. The only factors are: • whether both versions are on the classpath • the file modification time of the .classfile rules_clojure ( implements non-transitive AOT


@thheller we have used the shaded Closure dep for a long time to avoid those issues so I'm not sure what you are referring to


@dnolen The transitive dependencies will be AOT-ed too, but that doesn't mean you have to include those in your artifact


I believe has a filter feature for that


But will that work @alexmiller didn't suggest that route?


If it does work and doesn't create other issues that seems simpler


As long as clojure/data/json.clj is also on the classpath for library users due to being a dependency, why wouldn't it?


AOT is not without corner cases far as I remember


ok, Alex probably knows more about this than I do, so I'll be looking forward to his opinion on this


A way around the AOT-ed CLJS artifact is to just use it as a git dep


For me personally it's not a huge problem as I usually use CLJS more as a tool rather than an application dependency


And it does make startup time faster when it's AOT-ed


I was fairly certain that AOT classes directly refer to other AOT classes and thus can't go back to loading clj files


but looking at the generated class file that doesn't seem to be the case


so just excluding the not-cljs-related AOT classes should be fine


@dnolen the problem with closure I'm referring to is this: closure doesn't declare its dependency on guava. yet you end up with a guava version in the closure compiler jar. eg.

Clojure 1.11.1
(require ')
( "com/google/common/collect/ImmutableMap.class")
#object[ 0x315df4bb "jar:file:/home/thheller/.m2/repository/com/google/javascript/closure-compiler-unshaded/v20210808/closure-compiler-unshaded-v20210808.jar!/com/google/common/collect/ImmutableMap.class"]
with just deps.edn
{:paths ["src"]
 :deps {org.clojure/clojure {:mvn/version "1.11.1"}
        org.clojure/clojurescript {:mvn/version "1.11.4"}}}
so tools.deps (or maven in general) won't know guava exists and not resolve conflicts accordingly. then depending on other dependencies that may bring in other guava and which was ends up first on the classpath you end up with possibly conflicting guava versions.


this is a problem I have to constantly help people debug and fix. at least once a month would be my guess and most commonly happens for people integrating their frontend build with the regular deps.edn or project.clj backend deps


this also didn't always use to be like this. closure used to declare the dependency properly and all was fine. some time ago they changed and basically distribute an uberjar instead.


its kinda hard to reproduce the closure dep issues since it comes down to undefined dependency ordering. if the dependency properly declaring guava gets loaded after the closure compiler everything may work if that lib is also happy with the guava version from the closure compiler. if not it breaks. if the declared guava gets loaded first the closure compiler itself may or may not break, depending on which version it is


but given how common guava is as a backend dependency this happens often enough to be annoying


enough side tracking though, that really has very little to do with the CLJS being AOT or not and is an entirely separate issue that really needs to be fixed on the closure side of things


with CLJS AOT the only actual problem I have helped people though is trying different tools.reader or data.json versions and wondering why they weren't seeing those versions being used


given that clojure will load AOT classes before .clj files by default


$ clj
Clojure 1.11.1
(require ')
( "clojure/tools/reader__init.class")
#object[ 0x315df4bb "jar:file:/home/thheller/.m2/repository/org/clojure/clojurescript/1.11.4/clojurescript-1.11.4.jar!/clojure/tools/reader__init.class"]


so even if you have a local version of tools.reader that you are trying to modify or something it will not be used


This is definitely does work. Clojure loads code per-class, and source files can load AOT and vice versa. The only factors are: • whether both versions are on the classpath • the file modification time of the .classfile rules_clojure ( implements non-transitive AOT