Fork me on GitHub
#clojurescript
<
2019-08-13
>
Silenced Ego05:08:53

@thheller Hello, I got shadow-cljs repl working with cider after some frustration. I understand now that a node process must be started on the compiled code, before the cljs repl can be used. I am curious why this is necessary, and why cider doesn't do it automatically

richiardiandrea07:08:16

This is more of a cider question and it boils down to the different Clojure runtime... historically cider has always assumed the JVM running your process also evals your code. With node this is not really true and therefore you need to add an additional step to the chain. The automatic node process launch, by the way, could be a good feature request against cider.

thheller07:08:34

with the :node-script and :node-library targets it is pretty much impossible to "run" them automatically

thheller07:08:53

:node-script you'll maybe want to pass some command line args or use stdin/stdout

thheller07:08:25

:node-library you are likely consuming from some other library/framework (eg. webpack, jest, etc)

thheller07:08:00

node-repl is a generic way to run a node process and pretty much the only thing you need if you just want a node repl

thheller07:08:08

build specific REPLs are far more complicated

Silenced Ego08:08:40

Thanks. That's really interesting. Do you know where I can get a basic /top level understanding of the build specific REPL? I read this from the docs "Most :target configurations automatically inject the necessary code for a ClojureScript REPL." So code is injected into the compiled node script or node-library, and that somehow interacts with the nREPL that is run?

thheller09:08:36

so there are 2 parts involved in a CLJS REPL

thheller09:08:45

the compiler part running in shadow-cljs on the JVM

thheller09:08:25

that takes your input, generates JS for it, transports it to the JS runtime, evals it there, transports the result back to the JVM and that transports it back to you

thheller09:08:46

if the input was received via nREPL (JVM-side) it is also returned that way

thheller09:08:11

the JS runtime is the key here

thheller09:08:16

for the browser that is just the browser

thheller09:08:23

for node things that is typically a node process

thheller09:08:49

but there are many other possible runtimes as well (eg. react-native)

thheller09:08:16

the build specific part isn't any different than node-repl

thheller09:08:31

the ONLY difference is that node-repl starts a managed JS runtime (ie. node process) for you

thheller09:08:25

that is just something that you can't do with build specific REPLs since it is impossible to tell which JS runtime you are actually going to use

thheller09:08:12

so yes the code required for REPLs is injected

thheller09:08:21

but you need to actually RUN it

Silenced Ego06:08:27

also my :target is node library if it matters

andy.fingerhut19:08:30

Are there any handy examples of ClojureScript tests based on clojure.test that read data from a file checked into the project's repository? In Clojure/Java there is http://clojure.java.io/resource commonly used to find a file's full path based upon input of a relative path name, on the classpath, but not sure what common techniques would be for ClojureScript there. It is OK if it only works for Node.js in my particular case.

andy.fingerhut20:08:19

OK, Googling around Node.js docs helps. I can run the following in a nodejs interactive session, but not yet finding how to do the JS 'require' in ClojureScript. Any hints on how I can achieve that in cljs?

$ node
> var fs = require('fs')
undefined
> var contents = fs.readFileSync('CONTRIBUTING.md', 'utf8');
undefined

thheller20:08:13

(js/require "fs") with regular CLJS works

thheller20:08:34

not sure if the ns variant works outside of shadow-cljs

andy.fingerhut20:08:18

That worked, thx. And the obvious follow-up question is how I can then do that readFileSync call? Sorry, I have actually tried a few variations of guessed interop syntax here, but I don't have the rules in head yet.

thheller20:08:14

if you use regular requite you just (def fs (js/require "fs")) and then (.readFileSync fs "foo.edn")

andy.fingerhut20:08:33

ah, got it. I was missing the 'def' on 'fs' first.

thheller20:08:45

(ns foo.bar
  (:require ["fs" :as fs]))

(fs/readFileSync "foo.edn")

thheller20:08:54

this works in shadow-cljs and might work in regular CLJS

andy.fingerhut20:08:58

cool. All working now. Thx for the help.

thheller20:08:59

I'm not actually sure anymore

dnolen20:08:21

strings have no semantic meaning - they're just allowed for requires

dnolen20:08:31

but for fs not necessary

dnolen20:08:40

(require fs) is sufficient

andy.fingerhut20:08:19

Hmm, at least at a Node-based cljs REPL, (require fs) gives an error. Not sure if it is expected to work in that context, though.

thheller20:08:34

(require 'fs)

dnolen20:08:42

oh yeah sorry

dnolen20:08:36

there's a little bit of nastiness around Node namespaces and load-file - hoping to get that sorted out for the next release

andy.fingerhut20:08:45

(require 'fs) gives 'No such namespace: fs', but again, I might be stretching things with the REPL here. Not sure. The (def fs (js/require "fs")) gets me where I want to go, so no worries for me if other way does not work.

dnolen20:08:11

but I've been doing all Node.js ClojureScript development for a month or so now, it works great

andy.fingerhut20:08:44

Weird. It gives that error when I am connected via a socket REPL, but not when I start Node REPL via --repl-env node on the clj command line. I'm not going to shave that particular yak right now.

dnolen20:08:31

Socket REPL isn't heavily tested so - there be dragons

dnolen20:08:48

in general confirming behavior w/ it is not recommended

dnolen20:08:03

but bug reports welcome and patches too

andy.fingerhut21:08:29

I have been using Socket REPL with Node for a couple of weeks semi-heavily, but not necessarily stretching all kinds of weird corners -- mainly testing changes to core.rrb-vector library. This is the first time I recall seeing a difference between Node Socket REPL behavior and non-socket-REPL Node behavior.

dnolen21:08:33

ok that's good to know

dnolen21:08:41

also happy to hear it's working for you!