Fork me on GitHub
#shadow-cljs
<
2023-12-03
>
Pepijn de Vos10:12:59

I'm a bit puzzled how to split my code across a frontend and node part. Like, if I add multiple build targets, what defines which code ends up in them? This is what I currently have. Does it just infer the required code from the :init-fn and :export-var, or do I need something else?

{:source-paths
 ["src/dev"
  "src/main"
  "src/test"]

 :dependencies
 [[reagent "1.2.0"]
  [org.clojars.pepijndevos/hipflask "0.10.2"]]

 :dev-http {8080 "public"}
 :builds
 {:frontend
  {:target :browser
   :modules {:common {}
             :editor {:init-fn nyancad.mosaic.editor/init :depends-on #{:common}}
             :libman {:init-fn nyancad.mosaic.libman/init :depends-on #{:common}}}
   :compiler-options {:output-feature-set :es2018}}
  :extension
  {:target :node-library
   :output-to "out/main.js"
   :exports-var nyancad.mosaic.extension/exports}}}

thheller11:12:12

to be clear. two builds are entirely independent, they share nothing

thheller11:12:27

"code splitting" is what modules is, they split the build output itself into multiple files

thheller11:12:02

but yes, the compiler figures out what a build needs from its :init-fn or :exports-var

thheller11:12:22

basically it just follows and includes all :require namespaces from them

danielneal11:12:21

Dumb question - should / can I run the shadow-css build function in a shadow-cljs build hook? If so which stage?

thheller11:12:17

you should absolutely not do that 😛

thheller11:12:58

the way shadow-css works means its not coupled to CLJS in any way, thus triggering a build only in a hook makes no sense

thheller11:12:47

of course I cannot stop you from doing that, and the correct stage doesn't really matter since it doesn't need to modify or inspect the build state in any way

danielneal11:12:59

haha I”m glad I asked 😄

thheller11:12:59

but I strongly recommend not coupling them

danielneal11:12:25

what would you recommend, if I’m mainly going to be editing cljs files and would like the css to be regenerated on save?

danielneal11:12:50

Ok interesting - you mention that this could “just call (build/css-release)” … where would you recommend putting custom color variables like color-primary if you want to use the repl and the release build? Should I modify both the repl and the build css to assoc values into the build state?

thheller11:12:24

(defn my-css-modifications [state] ...)

thheller11:12:25

and here or so

thheller11:12:46

or make a common function that both call to get the basic build state

thheller11:12:21

note that in a different project I'm literally just calling css-release

thheller11:12:36

(defn start []
  (shadow-server/start!)

  ;; then setup the watcher that rebuilds everything on change
  (reset! css-watch-ref
    (fs-watch/start
      {}
      [(io/file "src" "main")]
      ["cljs" "cljc" "clj"]
      (fn [updates]
        (try
          (build/css-release)
          (prn :css-done)
          (catch Exception e
            (prn :css-build-failure)
            (prn e))))))

  (build/css-release)
  (prn :css-done)

  (let [inst
        (-> (sys/read-config "config/development.clj")
            (sys/start-system))]
    (vreset! instance-ref inst))

  :started)

danielneal11:12:41

Great, one more dumb question, where do I put repl.clj. I have a folder called dev and I put in repl.clj and called it repl.clj src/dev is in my paths But npx shadow-cljs run repl/start can’t find it

thheller11:12:24

that should be fine. what does "in my paths" mean?

danielneal11:12:51

I have a deps.edn and an entry :paths ["src/main" "src/test" "src/dev"]

thheller11:12:55

does that mean deps.edn? if shadow-cljs configured to use it?

danielneal11:12:10

and then in shadow-cljs.edn, :deps true

thheller11:12:25

did you restart shadow-cljs, in case you just added it?

thheller11:12:36

:paths changes are only picked up on restart

danielneal11:12:48

ah ok, wait I run shadow-cljs watch app, and then npx shadow-cljs run repl/start? It’s the npx repl/start that can’t find src/dev/repl.clj

thheller12:12:03

no, you no longer need to run watch

danielneal12:12:04

Am I missing something to start?

thheller12:12:22

you just run repl/start, and in that you do whatever you want to start besides shadow-cljs itself

thheller12:12:10

eg. in start you call (shadow/watch :app)

thheller12:12:21

shadow being shadow.cljs.devtools.api

thheller12:12:57

of course you can run the watch separately also, but you don't need to

danielneal12:12:15

Oh, I’ve cleared .shadow-cljs and it works now

thheller12:12:27

that is never necessary 😛

thheller12:12:56

I think you just deleted every trace of a still running shadow-cljs instance and you now may have a zombie instance in the background

thheller12:12:41

basically the way I work is that I have (repl/go) bound to a keybind in Cursive

thheller12:12:00

so whenever I need to "restart" my project I press that

thheller12:12:26

and every project has its own repl.clj to do project specific things

danielneal12:12:53

oh ok, great, thanks for your help! And that zombie is dead now I’m sure

thheller12:12:32

btw what I also do in the case of the shadow-cljs project itself, since it has so many builds for various things

thheller12:12:41

I just start them from the http://localhost:9630 UI

thheller12:12:18

since I'm not always working on all builds all the time that is more convenient than hardcoding it

thheller12:12:48

but starting the build from the start fn is equivalent to starting it from the terminal via npx shadow-cljs watch app otherwise

thheller12:12:58

so use whatever makes sense for you 🙂

danielneal12:12:08

Oh… is this wrong usage (css :bg-red-950) I’m getting the class generated in the html, but there’s no class in the css. The build is being run, and I see the tailwind preamble, but not the matching class

danielneal12:12:05

I also tried (css :c-bg-red-950)

danielneal12:12:48

and I’ve updated the namespace matcher in repl.clj

thheller12:12:38

I don't know what you mean

thheller12:12:15

in what context did you use (css :bg-red-950)

danielneal12:12:46

Like this

(defui app
  []
  ($ :div
     {:class (css :bg-red-950)}
     "hey"))

danielneal12:12:05

(ns qrart.homepage
  (:require [qrart.qr :as qr]
            [qrart.style :as style]
            [uix.core :as uix :refer [defui $]]
            [uix.dom]
            [shadow.css :refer [css]]
            ["react" :as react]
            ["react-dom" :as rdom]
            ["react-dom/server" :as server]))


(defui app
  []
  ($ :div
     {:class (css :bg-red-950)}
     "hey"))

(defonce root
  (uix.dom/create-root (js/document.getElementById "app")))
;; start your app with your favorite React renderer

(defn ^:dev/after-load init []
  (uix.dom/render-root ($ app) root))

thheller12:12:06

and the namespace is included in the css build?

danielneal12:12:30

(-> @css-ref
            (cb/generate '{:qrart {:include [qrart.*]}})
            (cb/write-outputs-to (io/file "public" "css")))
I think so ^ this is the relevant snippet?

thheller12:12:21

looks fine yeah

thheller12:12:51

did you leave in this kind of warning printer?

danielneal12:12:52

Ah, (css :px-4) works

danielneal12:12:59

I think it’s something to do with colors.

thheller12:12:04

that should warn about classes not existing

danielneal12:12:38

do I have to explicitly include the tailwind colors somehow?

thheller12:12:50

i.e. (css :bg-red-950) should get a warning since 950 doesnt exist

thheller12:12:37

this project has no direct match to tailwind, it is only inspired by it. so there are differences I guess

danielneal12:12:39

oh yeah, bg-red-900 is ok, I was looking at the tailwind site oop

danielneal12:12:05

I didn’t get a warn about bg-red-950 but I’ll check that later

danielneal12:12:29

Looking forward to using this in my project. I really like the idea and it’s nice not to have to run the tailwind node gubbins 🙂

danielneal12:12:46

It seems much simpler

👍 1