clojurescript

Drew Verlee 2025-02-09T21:51:35.766379Z

In the section https://clojurescript.org/reference/dependencies where would the file containing the yayQuery javascript logic go if the full deps.edn file looked like this:

{:deps {org.clojure/clojurescript {:mvn/version "1.11.54"}}
 :output-to "out/main.js"
 :externs ["yayquery-externs.js"]
 :foreign-libs [{:file "yayquery.js"
                 :provides ["yq"]}]}
i tried placing it on the src path so src/yayquery.js and the resource path (though i'm not sure thats included by default). I also tried an absolute path. Everything i tried resulting in not being able to find the namespace.

p-himik 2025-02-09T22:00:03.818459Z

> deps.edn Are you sure that's the file where that data should go?

Drew Verlee 2025-02-09T23:08:24.525219Z

Given it's not working, the answer is "no", i'm not sure of anything. The https://clojurescript.org/guides/quick-start just makes mention of deps.edn. The https://clojurescript.org/reference/compiler-options, where :foreign-key can be found. Makes no motion of where they should be used or consumed. the https://clojurescript.org/guides/externs page, which makes mention of build.edn, which it references contaning a :optimizations key, which also a key in the compiler options pages, so at this point i can assume the compiler options should go in a build.edn file. A google search for build.edn shows one written by dnolen, but not how its passed. It links to the quick start, where we might hope that running clj -M -m cljs.main --help might help? It does, we need to pass this build.edn to the -co option like this::

clj -M  -m cljs.main -co build.edn -c hello-world.core
But given the file doesn't matter, we could have passed the deps to i suppose. Though doing that gives us warnings about unknown compiler options. I think having the -co, --compiler opts reference the full set of options it can take, either by linking to the page, or having a further help section, would be nice. Similar a note on the https://clojurescript.org/reference/compiler-options page saying where, and how these might these should be passed would make sense to me as well. Is there any context in which those compiler options wouldn't be passed to the Clojure compiler? The way the https://clojurescript.org/guides/quick-start try to walk you towards understand this confusing to me. Like, the options are introduced, as if their worth mentioning right away, but not how they would be confused. Sure, you can figure it out, like we just did, but why introduce them in the docs then, a reader could also have jumped to other sources outside the tutorial to learn that as well. idk, its hard for me to say how to improve things for everyone. The easiest way for me to figure this out was to ask chatgpt how those compiler options were consumed.

p-himik 2025-02-09T23:13:57.966889Z

The docs can probably be improved, yes. If there's no relevant post at http://ask.clojure.org for it already, it would make sense to create one with a specific improvement suggestion.

πŸ‘ 1
shaunlebron 2025-02-10T04:29:23.831559Z

It’s possible that most people are reaching for shadow-cljs to handle this for them: β€’ https://shadow-cljs.github.io/docs/UsersGuide.html#npm-install β€’ https://shadow-cljs.github.io/docs/UsersGuide.html#js-deps

πŸ™ 1
thheller 2025-02-10T07:52:16.936519Z

I'd ask what you are trying to do in the first place? A whole bunch of people over the years that asked about this actually wanted to do something else entirely than what this is made for. :foreign-libs type bundling is definitely somewhat outdated and not done much anymore. shadow favors npm and even figwheel favors npm, although there via webpack in the middle.

thheller 2025-02-10T07:58:21.082359Z

but FWIW the :foreign-libs config goes into a deps.cljs file on the classpath. so src/deps.cljs (or whatever you use) not at the project root

thheller 2025-02-10T08:04:53.710419Z

:output-to and :externs are compiler options, so -co build.edn that part

thheller 2025-02-10T08:04:58.223069Z

:deps is deps.edn

Drew Verlee 2025-02-10T08:07:39.203579Z

I was trying to understand how interop, advanced compilation and externs work together by setting up a very minimal environment to do that in.

Drew Verlee 2025-02-10T08:12:18.414259Z

I'm collecting all my notes about the subject at the same time. So far, i haven't found clarity, so i'm still kinda messing around. I wouldn't care so much except every year i find myself on a new project with a different set of rules.

thheller 2025-02-10T08:12:41.959379Z

:advanced doesn't see or optimize :foreign-libs code. so your properties in the CLJS parts may get renamed while foreign code isn't. leading to breakage. externs prevent the renaming of the CLJS bits, so stuff still works.

thheller 2025-02-10T08:13:28.440779Z

that is it really. :advanced wants to rename everything by default, externs control what isn't renamed.

Drew Verlee 2025-02-10T08:18:55.431909Z

I'll ask the dumbest question, because thats usually the best one: Why doesn't it try to optimize the :foreign-libs? It seems like that would fix the problem if they were included. My guess is because most js libs break Google Closure Advanced complication restrictions (of which there seem to be many). So :foreign-libs is a safe boundary where we, the devsusing it, just assume they will break, and so don't try?

thheller 2025-02-10T08:21:56.729739Z

correct. :advanced is pretty strict and disallows some common JS patterns. they could actually still work in most cases but would require writing hand optimized externs. that is kinda hard to do for code you didn't write yourself, so most people do not bother even attempting

thheller 2025-02-10T08:22:16.542979Z

the attempt payoff is also very slim, so generally just not worth doing

thheller 2025-02-10T08:24:47.468479Z

note that :externs also cover code that you just can't include in a build. so there are by default externs added for all browser APIs. you just don't ever see those mentioned or configured anywhere. so :externs are not just for :foreign-libs, in fact they are for all "external code". so code that is not part of the optimization process.

πŸ‘€ 1
thheller 2025-02-10T08:29:17.347549Z

:foreign-libs is also just a fancy way of saying "prepend this stuff to my :output-to file". the code never even looks at the contents. it is just string concat basically

Drew Verlee 2025-02-10T08:30:17.762809Z

thanks πŸ™‚ that was basically the answer to the question i was trying to build.

πŸ‘ 1
Drew Verlee 2025-02-10T08:40:02.295929Z

Ok, yeah, the https://clojurescript.org/guides/externs clears up another question i have had: Whats the relationship between externs and type hinting? The guide says: > We simply need to type-hint x with the foreign type for this interop call... The compiler now has enough information to automatically generate the required externs.

Drew Verlee 2025-02-10T08:40:45.193469Z

Ill come back to this after some sleep. πŸ’€