Fork me on GitHub

I've got a hot code reloading question. I'm still in the process of trying to completely move away from the bootstrap build in shadow-cljs since it seems to create problems. I'm trying to integrate with borkdude's sci, which thus far seems relatively straightforward. I'm building a cljs repl using sci inside my application, which requires me to use a :dev/after-load hook to update sci's namespaces when I make an edit to my local cljs code while developing. The issue that I am having is, if I add a var to one of my normal cljs namespaces, when I tell sci to rebuild its namespace from the cljs one, it doesn't see the new var, unless some other one of my cljs namespaces makes an explicit reference to var. I imagine you don't necessarily know anything about sci, but can you tell me if there is anything unusual with hot code reloading related to creating a new var and having it be visible in a namespace?


That newly-created var is accessible from the js console directly. I'm having trouble figuring out how to re-require a namespace (since require can only be called at the top-level) to have the new var appear in my cljs namespaces.

Jakub Holý (HolyJak)12:04:10

Hello! Is there docs for shadow's api somewhere? I remember there was some function to load resources? I guess I was looking. for


Not sure about API docs but hopefully you’ll find this info helpful 👇 I actually had to use this last night from a CLJS namespace in order to inform shadow to watch some markdown files:

(shadow.resource/inline "./relative/path/to/")
It’s important to note that inline resolves the file relative to the file holding the namespace that’s calling inline - if that makes sense. Also, the argument to inline must be a string literal. If you need to load file paths dynamically, then you’ll need to create a macro like so:
(defmacro watch-corpus-files
     "Emits code that informs shadow-cljs to watch the corpus files for changes"
     (let [file-paths (corpus-file-paths)]
       `(do ~@(map (comp #(list 'shadow.resource/inline %)
                         #(str/replace-first % "src/cljs/owlbear/" "./"))


@U022T96EFV3 if you don't actually need the inline, you can maybe do what I described in the post above. just the metadata is enough, inline itself is not important


Ahhh, very true! The metadata approach is perfect for me :thumbsup:

Jakub Holý (HolyJak)17:04:01

@thheller thank you for the link! Is this information also somewhere in the Developer Manual (where I was looking for it, but without knowing the right keywords to search for)?


it is not no. I guess I never officially made a feature


@thheller I see there's a way to tag a namespace as always to be reloaded, but is there a way to do the same thing at the function level?


@pmooser no, only namespaces. I have indeed be thinking about something more fine grained but its a fairly complicated change to all caching code which I'd like to avoid for now


I have a user namespace that I use in development, activated with :init-ns user at the top level. I'm trying to make my first release build, so in the :main build I reset the REPL ns with :devtools {:repl-init-ns shadow.user, but it's still loading my user namespace for some reason. I use this same command to trigger the release build: Any idea why it's still starting with user? I have dev tools required in there that I don't want in a release.


@alex.sheluchin I don't know what "starting with user" means. what is you build config?


By that I mean that it loads the user namespace. I expect that if :repl-init-ns sets some other ns, user doesn't get loaded. But ofc that's not a valid expectation if repl-init-ns isn't relevant in release builds.

:builds   {:main     {:target     :browser
                       :output-dir "resources/public/js/main"
                       :asset-path "/js/main"
                       :dev        {:compiler-options {:external-config {:guardrails {:emit-spec? true :throw? false}}}}
                       :modules    {:main {:init-fn com.example.client/init}}
                       :js-options {:resolve
                                     {:target  :npm
                                      :require "@js-joda/timezone/dist/js-joda-timezone-10-year-range.min.js"}}
                       :devtools {:repl-init-ns shadow.user
                                  :preloads   [com.fulcrologic.fulcro.inspect.preload
                                  :after-load com.example.client/refresh
                                  :repl-pprint true}}


You mean the clojure user namespace I assume. that is always loaded by clojure, not controllable by shadow-cljs or anything else


Yes, that is what I mean.


Hmm, I thought it could be changed through the repl-init-ns setting. Guess I'm missing something foundational.


as I said. clojure will load this unconditionally, before shadow-cljs even gets a chance to do anything


the common strategy is to not have a user.clj on the classpath for CLJ projects


but since you asked about a CLJS release build I'm not sure how any of this is relevant?


Sorry, I think I'm a little mixed up about what shadow does exactly. It uses the JVM and the main part is built in Clojure, but it only produces CLJS builds? Is that correct?


yes, it is a build tool for CLJS


lol I know it's in the name and all 🙂 but I think all of the JVM-specific references in the docs made me confused about the boundaries of the tooling. When the docs are talking about using Clojure CLI to manage :source-paths and :dependencies (when using deps.edn), that is talking about CLJ only, not CLJS?


:source-paths and :dependencies apply to CLJS in exactly the same way as CLJ


Okay, thanks for the link and tips. I'll have a good read through that after some lunch and try making a build again.


repl-init-ns irrelevant for release builds


Hey yall, I followed these steps lein new reagent-frontend myproject +shadow-cljs cd myproject npm install npx shadow-cljs watch app and everything works, repl starts and compiles with no errors. Exept when I try and evaluate the ns. (ns rdomissue.core (:require [reagent.dom :as d])) Only reagent.dom gives me an error ; Could not locate reagent/dom__init.class, reagent/dom.clj or reagent/dom.cljc on classpath. Anyone know how to fix this? github repo: