Does the :esm target support calling js from clojure? It obviously supports calling cljs from js.. right?
I have a webpack project that i want to have lightweight minimum size cljs integrated with. Ideally cljs could use jquery and other npm libs and js functions from the project. And the project js could call a cljs fn to initialize the cljs funtionality.
I have had some success with :npm-module target before (doing the 2-way calling). But i struggled with bundle size issues, so i switched to ussing scittle. Now i want to try full cljs again. I was on an old version of Web pack before so that might’ve been part of the issue.
Does :esm supersede :npm-module if the js build supports esm modules? Or are there specific functionalities of :npm-library that can’t be replicated?
The warning can be hidden with jvm-opts:
Some internal dependencies still uses unsafe which triggers warning on the latest jdk version
yeah, but that option sounds like shadow-cljs is gonna do something nasty in some way. I haven't seen the guava one before though, so not sure whats going on there
yeah, I know that is has nothing with shadow-cljs, but this is the option we using internally for avoid see that warning every time we start a repl or shadow-cljs
yeah I have plans to switch to using jetty instead of undertow. that should get rid of them I hope
I don't think it is undertow, we are using undertow (our own binding) and the warning we see on starting backend is on netty:
that is so weird. how is everyone seeing different messages 😛
WARNING: A terminally deprecated method in sun.misc.Unsafe has been called
WARNING: sun.misc.Unsafe::objectFieldOffset has been called by org.jboss.threads.JBossExecutors (file:/Users/thheller/.m2/repository/org/jboss/threads/jboss-threads/3.5.0.Final/jboss-threads-3.5.0.Final.jar)
WARNING: Please consider reporting this to the maintainers of class org.jboss.threads.JBossExecutors
WARNING: sun.misc.Unsafe::objectFieldOffset will be removed in a future releaseWARNING: A restricted method in java.lang.System has been called
WARNING: java.lang.System::load has been called by com.sun.jna.Native in an unnamed module (file:/Users/thheller/.m2/repository/net/java/dev/jna/jna/5.16.0/jna-5.16.0.jar)
WARNING: Use --enable-native-access=ALL-UNNAMED to avoid a warning for callers in this module
WARNING: Restricted methods will be blocked in a future release unless native access is enabledIt all depends on the dependencies. on starting shadow-cljs i see the same warning that has been shown in this chat thread.
is what I get on java24
on starting penpot backend which uses undertow as http server, the warning is on Netty (is a dependency of AWS sdk, that has nothing in common with undertow)
still I'd rather not have these at all since they'll just confuse users and are completely meaningless, at least for now 😛
agree
> lightweight minimum size cljs
what do you expect here? I'd say about 90kb is the minimum, ~30kb gzip. that is CLJS only, goes up the more CLJS side stuff you add of course.
and yes it can do both ways
build size wise it won't get much smaller than :npm-module, a little but no more than 5% I'd guess
Thats fine, i think i was getting megabytes before!
probably didn't do a release (i.e. :advanced optimized) build then
watch/compile will always be several megabytes no matter what target
I thinks :advanced was breaking for me, so I turned optimizations down. But I’m really not bringing in any crazy libraries to cljs. It should be pretty straightforward, but it’s stumped me multiple times for multiple hours. Again, older Web pack and node versions in the mix were hard to rule out, but that’s been updated now.
webpack will have almost zero impact on this, so doesn't really matter which version
turning even to :simple will still be at least 2mb min I think. has been a while since I checked that.
Btw, the js build runs on node 20. That should be OK right? Since the shadow CLJS build runs in its own process on a newer version of nude.
also irrelevant. the build process runs on the JVM
if you had :npm-module working then thats about the baseline you can expect. just need a release build with full :advanced to get anything reasonable size wise
to answer the last part of your question :esm or :npm-module don't really matter if they run through webpack again anyway. the result is more of less identical. slightly better for :esm but very minimal and pretty much the only difference is how the interop looks
there is also an undocumented :esm-files target, which is pretty much :npm-module but instead of using commonjs require/exports uses ESM import/export ... but this is all really pretty much irrelevant with regards to build size
kinda hard to talk about in an abstract way, would help to have some actual code/examples 😛
Thanks. I’ll post a minimal repo. In a bit.
So with :esm-files i wouldn’t need to lint my fns with :export? And could use the :modules in shadow edn? If that worked for me, what would be the downside of just using the :esm target instead?
Also in this context of 2-way calling, i would need to set :js-provider right? To :external ?
:js-provider :import and I'd recommend setting up an alias on the webpack side. so that you can (:require ["@my-project/whatever.js" ...]) on the CLJS side and have webpack resolve that to src/whatever.js or so
can then also setup an alias to have import ... from "@cljs/foo.js" or so
:esm is a bit more verbose on the config side via :modules, leading to minimally smaller output (less boilerplate per ns)
:esm-files is same as :npm-module and requires individual :export tags yes, :esm does not since its all from the build config
I posted a minimal repo (minimal shadow-cljs, it has all the default js stuff from the project). cljs file https://github.com/GetBitOutdoors/theme/blob/minimal-shadow-cljs/src/gbo/core.cljs shadow.edn https://github.com/GetBitOutdoors/theme/blob/minimal-shadow-cljs/shadow-cljs.edn calling from js https://github.com/GetBitOutdoors/theme/blob/b3d92147f070a1799cd0e2f9f5920062dbcdbce5/assets/js/theme/product.js#L15C1-L20C53
With this current state shadow-cljs is failing to even compile. Giving this error:
:entries and :init-fn is not needed. only :exports, unless you actually want the :init-fn to be called when the script is loaded
:init-fn expects a singular symbol, so the error above is because of the extra vector
:init-fn gbo.core/my_cljs_fn, but again, seems misplaced here
Right now I using that fn double to test calling directly, and to load by default with module.
ah
:entries [gbo.core] is redundant because it is inferred from :exports and :init-fn
:dev {:compiler-options {:optimizations :simple}} does absolutely nothing because :dev builds do not apply any optimizations whatsoever (to CLJS code)
so if i have either of those, i don’t need :entries
correct
import cljs, { keyword } from "goog:cljs.core";
import { my_cljs_fn } from "/assets/js/cljs-output/core.js";
my_cljs_fn("cljs fn called explicitly from exports");
// module initialization should also run my_cljs_fn with default message
// call cljs fn explicitly from js
cljs.my_cljs_fn("cljs fn called with cljs keyword");this is basically all wrong
import cljs, { keyword } from "goog:cljs.core"; webpack has no clue what this is and it doesn't work
Ok cool. Shadow compiles now. But i do get these warnings
WARNING: A terminally deprecated method in sun.misc.Unsafe has been called
WARNING: sun.misc.Unsafe::objectFieldOffset has been called by com.google.common.util.concurrent.AbstractFuture$UnsafeAtomicHelper (file:/Users/ryan/.m2/repository/com/google/guava/guava/32.1.2-jre/guava-32.1.2-jre.jar)
WARNING: Please consider reporting this to the maintainers of class com.google.common.util.concurrent.AbstractFuture$UnsafeAtomicHelper
WARNING: sun.misc.Unsafe::objectFieldOffset will be removed in a future releaseimport { my_cljs_fn } from "/assets/js/cljs-output/core.js"; the :module was named :main, thus generating only assets/js/cljs-output/main.js
the warnings are kinda annoying, but not related to anything shadow-cljs does
java is getting a bit "loud" with their deprecation warnings
Ok. I tried running it and got this error from the project runner. Any insight? I havent customized any webpack config for this minimial test. There are 4 webpack config. files at the bottom of the repo. I’m not sure where to start. (ps I haven’t read up on the aliases thing yet..)
I already told you that this is not supported and will not work in webpack. just remove that import, it has no substitute
if you want to create keywords from js add it to your exports
import { keyword, my_cljs_fn } from "/assets/js/cljs-output/main.js";
:exports {my_cljs_fn gbo.core/my_cljs_fn keyword cljs.core/keyword}
FWIW :release {:compiler-options {:optimizations :advanced}} in the build config also does absolutely nothing because its already the default
Its running!! I got the fn confirmations in the browser console! 🎉
Just for reference, the dev build stats from webpack. Gonna try release now.
Do i need to manually clear the output directory when changing builds (from dev to release?)
not really no
Ok. Browser test worked with release built too 🙌 The webpack stats from release:
looks about right. shadow-cljs can also generate build reports btw. https://shadow-cljs.github.io/docs/UsersGuide.html#build-report
> I already told you that this is not supported and will not work in webpack.
Were you referring to trying to load cljs as a symbol in the js file?
(which i think is what i did with :npm-module)
import cljs, { keyword } from "goog:cljs.core"; this line. all of it. every single thing 🙂
the only thing that you can use reliably is what is in your :exports basically
Ok, thanks for the clarification.
Now I’m trying to test calling a js function from cljs.
https://github.com/GetBitOutdoors/theme/blob/minimal-shadow-cljs/src/gbo/core.cljs
https://github.com/GetBitOutdoors/theme/blob/minimal-shadow-cljs/shadow-cljs.edn
https://github.com/GetBitOutdoors/theme/blob/b4ea52a57bde18b36ee9771463bb487e8b7d2bfd/assets/js/theme/product.js#L13C1-L24C1
https://github.com/GetBitOutdoors/theme/blob/minimal-shadow-cljs/stencil%20error.md
Is the :require ok?
I’m also unclear how to properly call a js function in that is inside a “Product” method, in the local js context..?
I already answered that as well. see Can't resolve 'product' in '/Users/ryan/dev/gbo/theme/assets/js/cljs/cljs-runtime' resolve 'product' ...
["product" :as product-page] as the require is technically correct
but webpack will see it as import * as X from "product" and must resolve that somehow
since its not a npm package is can't find it, thus the error above
and the JS code is exporting a default class. so not a function you will directly call, but instead a new object you'd need to instantiate first
"/assets/js/theme/product.js" as the require means shadow will try to find it on the classpath. I'd recommend going with a webpack alias as linked above, but you can write (:require ["esm:/assets/js/theme/product.js$default" :as Product])
then (.my_js_product_method (Product. i-dont-know-what-context-is))
or (:require ["esm:/assets/js/theme/product.js" :as product]) and (product/my_js_top_level_fn)