Fork me on GitHub
#shadow-cljs
<
2023-07-21
>
tomc19:07:02

Hi All, I'm having some trouble with dynamically loading modules when using the :esm target. It seems that the shadow.lazy namespace is not intended to be used with :esm, so I'm trying to use shadow.esm/dynamic-import. I can load my module if I give a specific URL, but I'd prefer to just give a symbol as we do with shadow.lazy/loadable. Is that possible?

thheller19:07:49

not with shadow.lazy/loadable as of now since that assumes shadow.loader will do the actual loading

thheller19:07:06

but I guess you could take the existing shadow/lazy.clj+cljs and modify it to use esm import instead

tomc19:07:44

Got it, thanks. So I'm correct that shadow.lazy isn't intended for use w/ :esm?

thheller19:07:21

correct, shadow.lazy is meant for :target :browser

👍 2
tomc19:07:40

Thanks, will look into that option

tomc19:07:11

Related to the above, is shadow.esm/dynamic-import only intended for use with the :esm target?

thheller19:07:57

correct, in can in theory work elsewhere but is not currently setup to do so. basically it only exists to work around an issue where the closure compiler yells at us for using js/import directly in code

tomc19:07:27

Is it possible to import es modules when using :browser target, or would that require code changes/a separate namespace from shadow.esm?

thheller19:07:35

I hope it becomes unnecessary at some point

thheller19:07:08

well look at that namespace. there is no code to change 😛

tomc19:07:45

hahaha yeah, just checked. Thanks, I'll just do something similar to what you're doing in my own code.

thheller19:07:09

the issue is that the closure compiler doesnt like dynamic import in the code and will fail

thheller19:07:52

so, we call shadow_esm_import instead of import, and then prepend window.shadow_esm_import = function(x) { return import(x); }; to the code AFTER closure the closure compiler is done

tomc19:07:56

Makes sense.

thheller19:07:03

and currently this prepend is only done for :target :esm, so other targets just get a var not found error

tomc19:07:05

Seems like it would be possible for me to give you a PR that adds that code when shadow.esm is used anywhere in the project, right? Then dynamic-import could support other build targets.

thheller19:07:44

again, this is a hack that I hope becomes unnecessary. I don't really want to "spread" it further

thheller19:07:22

and you can do it yourself

thheller19:07:58

in the build config :modules {:main {:prepend "window.shadow_esm_import = function(x) { return import(x); };" :init-fn ...}}

thheller19:07:16

then you can use shadow.esm/dynamic-import just fine. assuming you are still in a browser of course, otherwise you might need to adjust the snippet

tomc19:07:54

That's perfect, thanks. Would you take a PR for the user guide describing this stuff in a bit more detail so that when I revisit this code in 6 months I have a place to look to understand what's happening?

ccann21:07:51

I’m trying to include a different source file (for build-specific vars that toggle app behavior) for each of my builds. I can’t specific :source-paths inside the build. Is there a recommended alternative approach?

ccann22:07:28

I put something together with a pre-compilation build hook that reads the build id and spits a file into the src for the given build

thheller05:07:31

I consider this a horrific anti-pattern and it is therefore not supported out of the box

thheller05:07:43

do you have a specific example of why you'd want to do that?

thheller05:07:51

in general the shadow-cljs builds ONLY include what they required, so if you have different builds each build would get its own entry namespace. that namespace you can use to setup build specific things since the others won't include it

ccann15:07:05

Thanks for the help — I’m trying to port an old lein/figwheel project and that project used build-specific :source-paths to bring in a namespace to the build which contained config. I’ll try out the options you mentioned