Fork me on GitHub
#shadow-cljs
<
2022-04-27
>
pmooser09:04:24

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?

pmooser09:04:21

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 https://github.com/thheller/shadow-cljs/blob/master/src/main/shadow/resource.clj#L53

sansarip14:04:34

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/file.md")
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/" "./"))
                   file-paths))))

thheller16:04:58

@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

sansarip16:04:57

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)?

thheller17:04:16

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

pmooser17:04:09

@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?

thheller17:04:44

@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

sheluchin18:04:14

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: https://github.com/fulcrologic/fulcro-rad-demo/blob/develop/Makefile#L8= Any idea why it's still starting with user? I have dev tools required in there that I don't want in a release.

thheller18:04:14

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

sheluchin18:04:19

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
                                     "@js-joda/timezone"
                                     {: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
                                               com.fulcrologic.fulcro.inspect.dom-picker-preload]
                                  :after-load com.example.client/refresh
                                  :repl-pprint true}}

thheller18:04:03

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

sheluchin18:04:17

Yes, that is what I mean.

sheluchin18:04:24

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

thheller18:04:16

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

thheller18:04:36

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

thheller18:04:56

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

sheluchin18:04:38

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?

thheller18:04:14

yes, it is a build tool for CLJS

sheluchin18:04:48

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?

thheller18:04:02

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

sheluchin18:04:15

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

thheller18:04:53

repl-init-ns irrelevant for release builds

fullNameHere19:04:16

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: https://github.com/SantoHerrera/issueswithrepl