Fork me on GitHub
#clojurescript
<
2022-08-15
>
winsome21:08:43

How do conditional requires work? I've got a cljc file where some of the :requires are only used in node. I don't want to require them at all in the browser. Right now I've got #?@(:cljs [["fs" :as fs] ["path" :as path]]) but that blows up when I try to build for the browser.

winsome21:08:48

I've also tried using :closure-defines as a conditional and doing the require dynamically, but that doesn't work for either build.

#?(:cljs
   (when-not platform/BROWSER
     (require '["fs" :as fs])
     (require '["path" :as path])))

lilactown21:08:49

in general you can't do conditional requires in CLJS

winsome21:08:53

ha, I'm learning that! How is this problem generally solved, then? Is building for the browser and for node in the same project not supported?

lilactown21:08:24

if you depend on some platform specific library, then what I typically do is split them into different namespaces

lilactown21:08:53

so you might have my-lib.core and my-lib.node, where my-lib.node has the nodejs-specific code

lilactown21:08:53

if you can push the I/O to the edges of your library, then my-lib.node can be quite small. you might realize you don't even need it

winsome21:08:05

Well, I suppose the whole namespace only makes sense on the jvm and node - it's writing the the filesystem. I guess I'll try putting the call site behind a closure-defines conditional and see if dead code elimination will remove it from the browser build

lilactown21:08:30

if it's writing to the filesystem, does it make sense to use it in the browser?

winsome21:08:16

It's just one corner of functionality of the overall package - offering a state-persistence mechanism. The rest of the library works just fine if you don't choose to use it that way.

winsome21:08:28

Eyy, it worked! Thank you DCE!

isak22:08:01

Another strategy is to have some source paths be different for different builds. E.g., for node: {"src/main" "src/node"]

isak22:08:47

Then you'd refer to "my-lib" and have it use either node/my-lib.cljs or some other implementation depending on the build paths.

winsome03:08:31

I actually find that approach pretty compelling. Though, if I'm targeting specific files within the ns hierarchy the directory structure will look a bit funny. But that could be ok

1
skylize23:08:42

In this https://github.com/sauvala/cljs-vscode-extension/blob/main/src/cljs_vscode_extension/main.cljs of a HelloWorld for building a VS Code extension from ClojureScript, the author uses what looks to be a type hint for a vscode.ExtensionContext instance.

(defn activate [^js/vscode.ExtensionContext context]
  (.log js/console "Congratulations, cljs-vscode-extension is now active!")
Is that actually what this does? If so, how might I discover what other types are hintable beyond js, clj, and basic primitives?

p-himik01:08:46

From the compiler perspective, that type hint is equivalent to ^js. Apart from that, it's just documentation.

skylize01:08:59

Thanks. That was my first guess (right after the brief moment when I took it at face value as a hint). Are fake hints like that common, popular, suggested? Can't quite decide whether it strikes me as a good idea.

p-himik03:08:20

FWIW, I almost never see them and don't use them myself.

pez07:08:55

I had no idea you could do that. Where is it documented?

pez07:08:11

Thanks. Maybe I am not reading it correctly, but it does seem like the /Foo.Bar actually is significant there?

p-himik07:08:54

The externs file might differ but I'm 90% certain that the end result of the compilation will be exactly the same - even if you mark the object on which you call .x with different types in different locations.

pez08:08:22

Thanks again! Makes sense.

skylize19:08:09

I guess specifying the class here is actually fairly meaningful documentation, as it explains why we need externs. If replacing a JS dep with a CLJ dep, you could use these hints to track down where externing is no longer needed. In this case it tells you clearly that this is provided by the VS Code environment and so will always need to be externed, while also implying that you can find documentation on Microsoft's website, by searching for "extensioncontext".