Search code examples
node.jsclojurescriptshadow-cljsvscode-calva

How to connect a ClojureScript node REPL to my :node-library shadow-cljs project?


Context

I am building a Node.js library with ClojureScript and shadow-cljs.
All development is done with ClojureScript but the build artefact is a NPM package. Example:

(ns com.example.answer)

(defn answer [] 42)

build... release... then

const answer = require('answer');
answer(); //=> 42

NB: I recently contributed the details of my build setup to this post.

My entire development environment is in a Docker container and I am using the "Visual Studio Code Remote - Container" extension.

The "Problem"

My build setup works fine (at least I think so!) but I'd like to implement a faster development feedback cycle.
In other words: I don't want to rebuild an entire NPM package just to test a few lines of change.

The Perfect World aka "the question"

In a perfect world I should be able to have a REPL open and be able to evaluate my ClojureScript code at all time.

No matter how I try to get there I seem to be blocked by the same underlying problem:

No application has connected to the REPL server. Make sure your JS environment has loaded your compiled ClojureScript code.

What I tried

  1. With shadow-cljs only:

    Given the following shadow-cljs.edn file:

    ;; shadow-cljs configuration
    {:source-paths
    ["src"]
    
    :builds
    {:lib {:target :node-library
            :output-to "dist/index.js"
            :exports {:citation citegen.processor.main/citation}}}}
    

    First watch:

    root@97db64e5dfa3:/workspaces/citegen# cd packages/csl-processor/
    root@97db64e5dfa3:/workspaces/citegen/packages/csl-processor# yarn shadow-cljs cljs-repl lib
    yarn run v1.17.3
    $ /workspaces/citegen/node_modules/.bin/shadow-cljs cljs-repl lib
    shadow-cljs - config: /workspaces/citegen/packages/csl-processor/shadow-cljs.edn  cli version: 2.8.52  node: v12.10.0
    shadow-cljs - socket connect failed, server process dead?
    shadow-cljs - updating dependencies
    ...
    shadow-cljs - dependencies updated
    shadow-cljs - server version: 2.8.52 running at http://localhost:9630
    shadow-cljs - nREPL server started on port 36017
    [0:0]~cljs.user=>
    

    Then in another terminal: (note the error message)

    root@97db64e5dfa3:/workspaces/citegen# cd packages/csl-processor/
    root@97db64e5dfa3:/workspaces/citegen/packages/csl-processor# yarn shadow-cljs cljs-repl lib
    yarn run v1.17.3
    $ /workspaces/citegen/node_modules/.bin/shadow-cljs cljs-repl lib
    shadow-cljs - config: /workspaces/citegen/packages/csl-processor/shadow-cljs.edn  cli version: 2.8.52  node: v12.10.0
    shadow-cljs - connected to server
    [1:1]~cljs.user=> (inc 41)
    No application has connected to the REPL server. Make sure your JS environment has loaded your compiled ClojureScript code.
    
  2. With VS Code Calva:

    Given the same shadow-cljs.edn file as above:

    enter image description here

    When I try to manually load the namespace with Calva: Load current namespace in REPL window, I get the same error:

    No application has connected to the REPL server. Make sure your JS environment has loaded your compiled ClojureScript code.

Question: How do I get to that perfect world?


Solution

  • Thanks to Thomas Heller I have managed to get this to work.

    What I didn't realise was that I needed to run the build artefact once in order to connect to the REPL.

    This will effectively get rid of this error:

    No application has connected to the REPL server. Make sure your JS environment has loaded your compiled ClojureScript code.

    Steps

    1. In VS Code open any ClojureScript file
    2. Press CMDSHIFTp and select Calva: Start a project REPL and connect (aka Jack-in)
    3. Wait until the REPL window opens
    4. Only then, open a new terminal and require your build artefact so that a connect to the REPL is made. e.g. node -e "require('./dist')"
    5. Open any ClojureScript file you want to evaluate in the REPL, press CMDSHIFTp and select Calva: Load current namespace in the REPL window

    I have attached a screencast below. As you can see:

    • The namespace in the CLJS REPL window isn't set to undefined anymore
    • Any change to your ClojureScript file is both automatically recompiled and available in the REPL

    enter image description here