Fork me on GitHub
#cljs-dev
<
2019-11-11
>
slipset15:11:53

My colleague is maintaining clj-refactor, and has this issue going on:

slipset15:11:18

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

slipset15:11:55

My question is that correct, and if so, why?

bronsa15:11:07

cljs doesn't have a resident compiler (self hosted cljs does) like clojure, which is required to provide eval and thus require

borkdude15:11:11

I also expect "dynamic" or "conditional" require to give problems with google advanced compilation?

borkdude15:11:18

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

dnolen15:11:40

@slipset the simplest answer is that ClojureScript is meant to be whole program optimized by Closure

dnolen15:11:57

that means no dynamic loads - because then that strategy falls apart

dominicm15:11:10

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.

dnolen17:11:17

Google Closure support dynamic loads during dev to avoid the compile step yes

dnolen17:11:29

but you should not embed require into arbitrary locations

dnolen17:11:38

we don't test this nor care if it doesn't work

dnolen17:11:23

the only thing that we support is top level require before any other statements

dnolen17:11:24

@dominicm load-file is not supported

dnolen17:11:29

except at the REPL

dominicm17:11:24

Hmm. Frustrating. I suppose multiple ns generated by a macro wouldn't be supported either?

dominicm17:11:23

The goal is to combine colliding namespaces into one.

dnolen17:11:20

one namespace per file - and load-file could never work

dnolen17:11:54

@dominicm I don't understand what problem you're trying to solve - "colliding namespaces"

dominicm17:11:43

@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.

dnolen17:11:56

user.cljs works already

dnolen17:11:06

just require whatever you want there

lilactown17:11:46

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

dnolen17:11:07

@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

dominicm17:11:57

I should say I haven't tested, I assumed the behavior matched clojure. I'm talking about the case that there's 2 user.cljs files on the classpath. You're saying that they're already both loaded and run? Oh, I also meant cljs/user.cljs, is that the same?

lilactown17:11:49

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 time

dominicm17:11:57

I should say I haven't tested, I assumed the behavior matched clojure. I'm talking about the case that there's 2 user.cljs files on the classpath. You're saying that they're already both loaded and run? Oh, I also meant cljs/user.cljs, is that the same?

lilactown17:11:03

it’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)

dnolen17:11:15

@dominicm clojure loads them all

dnolen17:11:40

or that was my understanding anyway

dominicm17:11:50

I don't think so. Not when I was playing with it. First in the path won.

dnolen18:11:21

oh sorry you're right I was thinking about a different problem that we solved

dnolen18:11:46

which is that you can have N files which don't declare a ns

dnolen18:11:02

so we do some magic to make sure that these get defined in cljs.user

dnolen18:11:58

@dominicm but note user.clj is just a convenience

dnolen18:11:22

nothing is stopping you from starting a REPL that loads your thing as well

dnolen18:11:26

so I'd say stop messing around with user.clj

😈 4
dnolen18:11:48

make a file called my_dev.clj and load that into your REPL

dnolen18:11:53

this should also work for ClojureScript

dnolen18:11:29

you can use an alias if you want to avoid repeating yourself of course

lilactown18:11:07

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.

4
dominicm18:11:04

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.