Shadow-cljs + node-script + REPL crashes if any eval happens. Browser devtools are being included

Hello, I work on a project written in clojurescript. It runs on NodeJS and is compiled using shadow-cljs with :node-script as a target.

For reference, here is the shadow-cljs build definition:

          {:target :node-script
           :output-to "target/dev.js"
           :output-dir "target"
           :compiler-options {:reader-features #{:nodejs}}
           :main platform-unfurler.dev/start!
           :devtools {:after-load platform-unfurler.dev/start!
                      :before-load platform-unfurler.dev/stop!}}

Everythings works fine until I connect to it via REPL and try to eval any form. The node process crashes with the following stack trace:

SHADOW import error /app/target/cljs-runtime/shadow.cljs.devtools.client.browser.js

/app/target/cljs-runtime/shadow/cljs/devtools/client/env.cljs:264
  (js/$CLJS.SHADOW_ENV.isLoaded name))
   ^
TypeError: Cannot read property 'isLoaded' of undefined
    at Object.shadow$cljs$devtools$client$env$goog_is_loaded_QMARK_ [as goog_is_loaded_QMARK_] (/app/target/cljs-runtime/shadow/cljs/devtools/client/env.cljs:264:4)
    at shadow$cljs$devtools$client$env$src_is_loaded_QMARK_ (/app/target/cljs-runtime/shadow/cljs/devtools/client/env.cljs:273:8)
    at Function.G__29389__1 [as cljs$core$IFn$_invoke$arity$1] (/app/target/cljs-runtime/cljs/core.cljs:4312:16)
    at /app/target/cljs-runtime/cljs/core.cljs:5219:22
    at /app/target/cljs-runtime/cljs.core.js:19237:3
    at Object.sval (/app/target/cljs-runtime/cljs/core.cljs:3462:18)
    at Object.cljs$core$ISeqable$_seq$arity$1 (/app/target/cljs-runtime/cljs/core.cljs:3452:1)
    at Object.cljs$core$seq [as seq] (/app/target/cljs-runtime/cljs/core.cljs:1236:13)
    at Function.cljs$core$IFn$_invoke$arity$3 (/app/target/cljs-runtime/cljs/core.cljs:2498:26)
    at Object.cljs$core$IReduce$_reduce$arity$3 (/app/target/cljs-runtime/cljs/core.cljs:3529:28)
    at Function.cljs$core$IFn$_invoke$arity$3 (/app/target/cljs-runtime/cljs/core.cljs:2570:17)
    at Function.cljs$core$IFn$_invoke$arity$2 (/app/target/cljs-runtime/cljs/core.cljs:5266:35)
    at Object.shadow$cljs$devtools$client$shared$IHostSpecific$do_repl_init$arity$4 (/app/target/cljs-runtime/shadow/cljs/devtools/client/browser.cljs:219:14)
    at Object.shadow$cljs$devtools$client$shared$do_repl_init [as do_repl_init] (/app/target/cljs-runtime/shadow/cljs/devtools/client/shared.cljs:21:18)
    at Object.shadow$cljs$devtools$client$shared$interpret_action [as interpret_action] (/app/target/cljs-runtime/shadow/cljs/devtools/client/shared.cljs:139:6)
    at Object.shadow$cljs$devtools$client$shared$interpret_actions [as interpret_actions] (/app/target/cljs-runtime/shadow/cljs/devtools/client/shared.cljs:207:8)
    at /app/target/cljs-runtime/shadow/cljs/devtools/client/shared.cljs:256:15
    at Object.shadow$remote$runtime$shared$process [as process] (/app/target/cljs-runtime/shadow/remote/runtime/shared.cljc:164:16)
    at Object.shadow$cljs$devtools$client$shared$IRemote$remote_msg$arity$2 (/app/target/cljs-runtime/shadow/cljs/devtools/client/shared.cljs:289:8)
    at Object.shadow$cljs$devtools$client$shared$remote_msg [as remote_msg] (/app/target/cljs-runtime/shadow/cljs/devtools/client/shared.cljs:16:16)
    at WebSocket.<anonymous> (/app/target/cljs-runtime/shadow/cljs/devtools/client/node.cljs:64:12)
    at WebSocket.emit (events.js:400:28)
    at Receiver.receiverOnMessage (/app/node_modules/ws/lib/websocket.js:983:20)
    at Receiver.emit (events.js:400:28)
    at Receiver.dataMessage (/app/node_modules/ws/lib/receiver.js:517:14)
    at /app/node_modules/ws/lib/receiver.js:468:23
    at /app/node_modules/ws/lib/permessage-deflate.js:308:9
    at /app/node_modules/ws/lib/permessage-deflate.js:391:7
    at afterWrite (internal/streams/writable.js:466:5)
    at onwrite (internal/streams/writable.js:446:7)
    at InflateRaw.afterTransform (internal/streams/transform.js:103:3)
    at Zlib.processCallback (zlib.js:607:8)

I am starting shadow using watch followed by node target/dev.js as per the docs. I can connect to the REPL and also select the shadow build, it’s crashes only when doing any eval.

The only thing in the stack trace that caught my attention was this:

SHADOW import error /app/target/cljs-runtime/shadow.cljs.devtools.client.browser.js

I am not why it’s trying to include the browser devtools.

Any help on how to solve this would be greatly appreciated as living without the REPL is becoming harder as the project grows.

A :node-script build will not include this file on its own. Do your sources require the shadow.cljs.devtools.client.browser ns manually somewhere? Do you maybe output another build into the :output-dir "target" that may override files from each other?

Thanks a lot @thheller. I found the culprit.
It’s a monorepo and a reference to another project was including shadow.cljs.devtools.client.browser. It was required in cljs.user namespace of that project which are included automatically. Renaming the file and loading it via :preload did the job.

Note that there really is no need to require the shadow.cljs.devtools.client.browser namespace. shadow-cljs will add it itself when needed.