My colleague is maintaining clj-refactor, and has this issue going on:
Somewhere near the bottom it is stated (with reference to the docs) that require
in cljs is only to be used from the repl: https://cljs.github.io/api/cljs.core/require
My question is that correct, and if so, why?
cljs doesn't have a resident compiler (self hosted cljs does) like clojure, which is required to provide eval and thus require
I also expect "dynamic" or "conditional" require to give problems with google advanced compilation?
Wasn't there something that the compiler tries to work with top-level requires at the start of the namespace? but that's pretty limited
@slipset the simplest answer is that ClojureScript is meant to be whole program optimized by Closure
that means no dynamic loads - because then that strategy falls apart
Kinda related: is it okay to do dynamic loads for development? I was thinking of writing a user.cljs which made conditional calls to load-file.
Google Closure support dynamic loads during dev to avoid the compile step yes
but you should not embed require
into arbitrary locations
we don't test this nor care if it doesn't work
the only thing that we support is top level require
before any other statements
@dominicm load-file
is not supported
except at the REPL
Hmm. Frustrating. I suppose multiple ns
generated by a macro wouldn't be supported either?
nope
The goal is to combine colliding namespaces into one.
one namespace per file - and load-file
could never work
@dominicm I don't understand what problem you're trying to solve - "colliding namespaces"
@dnolen I want a way to load code for my development (without modifying the project I'm on). It followed to me that user.cljs is for the user, not for projects, but projects override it anyway. So the idea was to have my user.cljs load the project user.cljs. One constraint is that it should work with a large number of projects you'd find in the wild. Consistently no matter if they're using cljsbuild, deps, etc.
user.cljs
works already
just require whatever you want there
I think there are two ways you can do what you want dominicm (only load some code when in development):
The first and easiest way is to use (when goog/DEBUG ...)
to define the stuff you want to happen only at DEV time. this should get DCE’d when a release build is run. This works across lein-cljsbuild/deps+figwheel/shadow-cljs
@dominicm you cannot "override" user.cljs
by the way - we'll load them all - if it doesn't work for some reason you should report a bug with some kind of minimal reproduction
this doesn’t work when you want to optionally load a dependency (e.g. an external JS lib), so in that case you have to do something grosser,,,: - set up points in your code that should interact with the code you want to optionally load. something like:
(when (and goog/DEBUG (.-someFn js/someCoolThing))
(.someFn js/someCoolThing))
- instruct the user to add a my-lib.some-cool-thing
that sets up js/someCoolThing
into their preloads or user.cljs at DEV timeit’s a PITA from a lib maintainer POV, but from a user POV they just need to make sure they include the side-effecting ns before any code that uses it (which is why preloads is preferred)
@dominicm clojure loads them all
or that was my understanding anyway
I don't think so. Not when I was playing with it. First in the path won.
oh sorry you're right I was thinking about a different problem that we solved
which is that you can have N files which don't declare a ns
so we do some magic to make sure that these get defined in cljs.user
@dominicm but note user.clj
is just a convenience
nothing is stopping you from starting a REPL that loads your thing as well
so I'd say stop messing around with user.clj
make a file called my_dev.clj
and load that into your REPL
this should also work for ClojureScript
you can use an alias if you want to avoid repeating yourself of course
determining conditional ns at macro-time is something that comes up semi-often for frameworky stuff that I wish there was better support. I can work around it, but it’s onerous as the lib maintainer.
You're right of course. That's a small cost to pay for the functionality. I perhaps got too tied up in the fully automatic aspect.