@thheller is the ESM output of shadow-cljs relatively popular? there was some talk of switching to only that, is that going to happen? Reading over your notes I see that you made it work by just writing to globalThis in the CLJS output for vars?
but did shadow flip to this as the default?
re: "adds esm import/export after optimization" - this I can't parse. If it's optimized what is import for?
import for code splitting and in shadow-cljs there is the concept of :js-provider. default is :shadow as in shadow-cljs provides the npm dependencies. another is :import as in (:require ["react" ...]) becomes import ... from "react" in the final output so that other tools can process it
:modules
{:main
{:init-fn shadow.cljs.ui.main/init
:preloads [shadow.grove.dev-support
shadow.grove.preload]}
;; trying something to split out features not pages
;; maybe thats a better pattern overall, should be less config
:code-editor
{:entries [shadow.cljs.ui.components.code-editor]
:depends-on #{:main}}}}this is from the build config for the shadow-cljs ui. it lazy loads the code-editor (codemirror) when needed
or this is another dummy config
:modules
{:shared {}
:a
{:exports
{default demo.esm.a/foo
foo demo.esm.a/foo
bar demo.esm.a/bar}
:init-fn demo.esm.a/init
:depends-on #{:shared}}
:b
{:exports
{default demo.esm.b/bar}
:depends-on #{:shared}}
:c
{:exports
{default demo.esm.c/foo}
:depends-on #{:b}}}so from js you can import X from "./a.js" and that is the default export, so it gets the value of demo.esm.a/foo
useful in environment that expect your files to have certain exports, like a default export. some tools expect that and don't work otherwise
so the way this is done is shadow-cljs adds "markers" to the code that :advanced will optimized but not eliminate. those markers are then later replaced with actual export ... statements
https://github.com/thheller/shadow-cljs/blob/344ce44739b0b524c438cf63bc0d6de58555d5dd/src/main/shadow/build/closure/ShadowESMExports.java not a whole lot of code, but only way I could find to make export actually work (in optimized builds)
basically its all just normal :advanced output, just post processed a bit
shadow-cljs doesn't have a default when it comes to build configs. people chose which :target to use. I'd say most still use :browser, but I recommend and have helped a few people to switch to :esm. mostly to make life with code splitting and dynamically loading stuff easier
also have stuff for actual "ESM", but doubt anyone ever actually used this
(ns demo.esm.a
(:require
["" :as x])) that just becomes a normal import ... from ". meaning shadow-cljs won't try to bundle it and stuff is loaded at runtime by the browser
little things, mostly to get to something that can actually make full use of ESM
for development it just fakes ESM. basically just exports everything to globalThis yes. for optimized builds it generates normal optimized output (with code splitting) and then adds esm import/export after the optimizations. can't have the closure compiler see those, since it will compile them away. optimized code is ESM compliant and does not export anything into globalThis. this is important so that other tools can actually work with it properly.
my recommendation is to only use ESM these days. it makes a lot of things much simpler and the interop is just better
not to mention you can just import() things dynamically without the need for the goog.module.ModulerLoader stuff
most of the work goes into working around the closure compiler being over eager and compiling everything away that we may want
also their output mode for ESM is kinda useless. can't influence what to export to the outside world at all, so not using that