shadow-cljs

https://github.com/thheller/shadow-cljs | https://github.com/sponsors/thheller | https://www.patreon.com/thheller
FHE 2021-05-11T01:57:23.055700Z

Super-basic question: In https://github.com/shadow-cljs/quickstart-browser , are the commands npx shadow-cljs server and npx shadow-cljs watch app both supposed to tie up the CLI window (I'm running this in WSL2) and require opening a new one for subsequent commands?

FHE 2021-05-11T02:01:05.056600Z

They seem like ongoing processes, so it makes sense to me. I just would like to make sure nothing's going wrong.

2021-05-11T02:08:46.056700Z

Your right, they both start a process.

FHE 2021-05-11T02:26:27.057300Z

Running google-chrome does as well? I've opened my 4th window now...

FHE 2021-05-11T02:28:56.058900Z

Sorry. Trying to learn a lot at once. To me it's strange to see a CLI echo responses to a command, then just...stop responding (without returning to a prompt). I've seen something similar with REPLs, but at least there you get some kind of prompt.

FHE 2021-05-11T02:36:08.063600Z

By the way, running the server command above responds that it starts an HTTP server at <http://localhost:8020>, another server at <http://localhost:9630>, and an nREPL server "on port 35301". I can navigate to the first two servers in my WSL2 browser (and even in a Windows browser), but I don't know what to make of the third. Actually, since it was telling me a REPL was being started I was kind of waiting for a REPL prompt to show up (but no).

FHE 2021-05-11T03:03:58.064100Z

How do I access this nREPL?

thheller 2021-05-11T07:06:25.079100Z

nREPL is the protocol used by most editors/tools. It is not directly used by humans. don't know what editor your are using but it most likely supports nREPL

FHE 2021-05-11T12:29:50.081700Z

Aha. Thanks. So if I figure out how to use CIDER, that is probably what it will hook into?

FHE 2021-05-11T03:36:44.067Z

Separate question: Is npx shadow-cljs watch app process in https://github.com/shadow-cljs/quickstart-browser supposed to cover index.html (and CSS files, I should ask) for live updating? ...or is there a way to get it to? The browser is not reacting to changes to it. I can hit F5, but I thought that was not supposed to be required with hot reloading.

thheller 2021-05-11T07:06:45.079300Z

css is hot-reloaded. HTML is not.

FHE 2021-05-11T12:30:24.081900Z

Fair enough. 👍

FHE 2021-05-11T05:27:11.074200Z

3rd question: How do you use cljs to set the text of the h1 in index.html? I've tried 20 different ways based on examples from a cljs cheatsheet and 3 or 4 other sources. Here are just some examples that have failed: 1.`(js/document.getElementsByTagName('h1')[0].innerHTML = 'Live reloaded')` 2.`(. js/document.getElementsByTagName('h1')[0].innerHTML = 'Live reloaded')` 3. (-&gt; js/document (.getElementsByTagName "h1" 0) (.-innerHTML) (set! "Live reloaded")) 4. (set! (.-innerHTML .getElementsByTagName "h1" "0" js/document) "Live reloaded") 5.`(def heading1 (.getElementsByTagName "h1" 0 js/document)) (set! (.-innerHTML "Live reloaded"))` 6. (def heading1 ([0] "h1" .getElementsByTagName js/document)) ;(set! (.-innerHTML "Live reloaded")) ...and I do realize state should be dealt with differently, like by using atoms and/or learning reagent, but for now I just want to try to get some kind of live reloading working. Thanks.

thheller 2021-05-11T07:08:56.079500Z

This is basic interop question. I suggest reading some code. There are a couple ways to do this but taking the JS and moving the parens is not the way 😉 One variant

(let [el (-&gt; (js/document.getElementsByTagName "h1")
             (aget 0))]
  (set! (.-innerHTML el) "yo"))

FHE 2021-05-11T12:36:18.082100Z

Big 'Aha.'. The (aget 0) part is a particular surprise. All of my attempts were pretty close to others' supposedly working code, by the way. Their code examples were mostly (or all?) for getElementById, though, which means they did not show how to handle an index number.

FHE 2021-05-11T13:04:46.089200Z

Kind of surprised the above doesn't work rearranged as a one-liner (avoiding using 'let'): (set! (.-innerHTML (-&gt; (js/document.getElementsByTagName "h1") (aget 0)) "Equivalent one-liner wihout 'let'?")) Not sure how half of the example working code I found out there was one-liners (again, at least for things referenced by Id---I wonder if not having to deal with that '0' makes the difference).

thheller 2021-05-11T13:20:06.090700Z

(set! (.-innerHTML (-&gt; (js/document.getElementsByTagName "h1") (aget 0))) "Equivalent one-liner wihout 'let'?")

thheller 2021-05-11T13:20:17.090900Z

gotta be careful with the placement of the parens .. the let for me makes the code easier to read, that is why I use it

FHE 2021-05-11T13:45:14.096Z

Sigh...basic paren mistake. Whoops. Thanks! ...and yes, I'm sure I'll want to not use hard-to-read one-liners going forward. For this instance I just wanted to see a working one-liner side-by-side with all my failed lines to compare and contrast. 😉

thheller 2021-05-11T13:48:24.096200Z

well as I said there are many ways to write this. so the most important step is learning what every part does.

(-&gt; (js/document.getElementsByTagName "h1") (aget 0) (set! -innerHTML "Equivalent one-liner wihout 'let'!"))
also works

FHE 2021-05-11T13:54:56.098800Z

Good to know. So many combinations. Hopefully it will sink it soon for me why the ones that work work and why the other examples from around the web did not (other than the aget(0) piece never being there).

FHE 2021-05-11T13:56:54.099Z

Appreciate your feedback very much. I'm sure I'll have another softball question (that I couldn't answer even after scouring the web) in about 12 hours when I can get back to this. Ha!

thheller 2021-05-11T13:58:09.099200Z

js/document.getElementsByTagName returns an array, aget gets the nth element of that array

thheller 2021-05-11T13:58:24.099400Z

js/document.getElementById only returns a singular element, not an array

FHE 2021-05-11T05:32:14.079Z

4th question: If I add example 5. above to my starter.cljs file (again, this is using the shadow-cljs quickstart project), I get errors. That's fine. It's bad code. No problem. ...but then if I comment that line of code out, then after a hot reload I still get the same error. How can that be?? This behaviour was hard to suss out, and made me have to re-try lots of code for trying to set that h1 text (after finding out that old, commented-out code, and not replacement lines of code I was trying to test, could be to blame for errors).

Aron 2021-05-11T11:02:58.080700Z

I am getting a variable module is undeclared warning from Resource: com/cognitect/transit.js:649:8 when I do release and I am not sure why, any pointer would be appreciated to what this is about.

thheller 2021-05-11T11:54:52.081400Z

you can ignore that one. you can create externs for module to get rid of it but it is safe to ignore

Aron 2021-05-11T12:03:59.081600Z

thanks

FHE 2021-05-11T12:42:24.084600Z

Further to my Q4 above, should I just assume that if my code causes an error (or at least the kind of error that shows up on an all-red banner), then after fixing/removing the offending code I need to force a reload of the webpage? That seems odd.

FHE 2021-05-11T12:49:45.089Z

(Errors on white with red border (e.g. "Compilation failed!", caused by my code line 4. above) reliably go away when code is reverted. Errors on white with yellow banner (e.g. "WARNING in start/browser.cljs", caused by my code line 6. above) also reliably go away when code is reverted. Errors on red banner (e.g. "shadow-cljs - [reload failed] Failed to load starter/browser.cljs: [...]", caused by my code line 5. above) persist even after removing the lines of code that caused them!)

thheller 2021-05-11T13:18:36.090100Z

@factorhengineering as the error says. it failed to load the file. that has nothing to do with the compilation. it can compile but still fail to load if the code is invalid. that will go away when you fix the code.

thheller 2021-05-11T13:19:12.090600Z

I don't know what code you are trying to load but all the examples you had were invalid and would cause an error during load

Aron 2021-05-11T13:28:12.092600Z

Empirical programming at its best. I remember FHE asking shadow-cljs questions in #beginners and thinking to myself that I should definitely not mention this channel yet. : ) Maybe I am too mean, but what I see is a lot of wasted effort by rushing ahead and by this, making things more difficult, even for people who would like to help.

thheller 2021-05-11T13:31:51.093700Z

definitely shows that we need a lot more documentation for all of this 🙂

FHE 2021-05-11T13:37:03.094200Z

or a #shadow-cljs-beginners kiddie pool. 😉

thheller 2021-05-11T13:39:30.095900Z

its fine to ask here. I'll answer when I have time.

Aron 2021-05-11T14:47:49.100100Z

I think the current documentation is extremely good, but it's written in a style that makes it difficult to consume

Aron 2021-05-11T14:48:14.100600Z

i've been actually planning to propose an alternative presentation for it, or a kind of rewrite

2021-05-11T15:24:56.102900Z

hello. if I have a watch build running, with a cljs repl connected, is there a way to temporarily prevent live-reloading in the browser, but keep the repl connected? with figwheel you have a stop function you can call to achieve this - I'm looking for the shadow equivalent. thanks

thheller 2021-05-11T15:33:52.103400Z

@henryw374 from the clojure REPL (shadow/watch-set-autobuild! :the-build-id true|false)

thheller 2021-05-11T15:34:38.104Z

no clue if anyone ever actually used that or if it works but I added it a long time ago 🙂

2021-05-11T15:41:07.105800Z

thanks again @thheller. it's working well 😉 I use that when I'm defining a bunch of temp vars with https://github.com/vvvvalvalval/scope-capture and don't want reload to lose the state

Franklin 2021-05-11T18:19:35.106500Z

I have figwheel code splitting configs that look like this

:modules
              {:organization
               {:entries #{app.components.organization.init}
                :output-to "target/cljsbuild/public/js/out/organization.js"}
               :home
               {:entries #{app.components.home.init}
                :output-to "target/cljsbuild/public/js/out/home.js"}
               :user-management
               {:entries #{app.components.organization.users.init}
                :output-to "target/cljsbuild/public/js/out/user-management.js"}
               :settings
               {:entries #{app.components.organization.settings.init}
                :output-to "target/cljsbuild/public/js/out/settings.js"}}

Franklin 2021-05-11T18:19:54.106600Z

so, for each module a single .js file is generated

Franklin 2021-05-11T18:22:05.107300Z

I get this error when I don't add :depends-on

ExceptionInfo: two modules without deps, please specify which one is the default

Franklin 2021-05-11T18:54:18.108Z

seems https://github.com/thheller/code-splitting-clojurescript/blob/c9e1e9340c45969f3fc5b515fb9d095f28595c24/src/main/demo/app.cljs uses a front end router and I wonder if I can set up code splitting without a frontend router

Franklin 2021-05-11T19:06:04.108700Z

actually, I think I might have figured this out... the documentation helped

thheller 2021-05-11T19:06:30.109Z

regular CLJS has an implicit base module that all of them depend on. shadow-cljs does not but you can add it and have them all manually depend on it

👍 1
thheller 2021-05-11T19:06:57.109200Z

just :shared {:entries []} and then all the other :depends-on #{:shared}

thheller 2021-05-11T19:07:29.109400Z

they are all written to the output-dir, no need for :output-to per module

👍 1
Franklin 2021-05-11T19:10:59.109700Z

thanks

john-shaffer 2021-05-11T19:30:19.112400Z

Thanks for the advice @thheller. In this case I'm not even using the feature, and I may be better off forking the library so I can stick with the default feature set The issue is that Material UI is (gradually) dropping IE 11 compat and starting to use newer ECMAScript features, so those options will probably be needed in the future. Hopefully they are less bleeding edge by then

thheller 2021-05-11T19:37:52.113400Z

yeah all that stuff is extremely messy

thheller 2021-05-11T20:25:31.114300Z

so nobody ever has to ask again why cljs.pprint was in their build 😉

lispers-anonymous 2021-05-14T16:52:01.272800Z

Thank you so much for doing this

😉 1