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?
They seem like ongoing processes, so it makes sense to me. I just would like to make sure nothing's going wrong.
Your right, they both start a process.
Running google-chrome
does as well? I've opened my 4th window now...
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.
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).
How do I access this nREPL?
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
Aha. Thanks. So if I figure out how to use CIDER, that is probably what it will hook into?
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.
css is hot-reloaded. HTML is not.
Fair enough. 👍
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. (-> 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.
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 (-> (js/document.getElementsByTagName "h1")
(aget 0))]
(set! (.-innerHTML el) "yo"))
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.
Kind of surprised the above doesn't work rearranged as a one-liner (avoiding using 'let'):
(set! (.-innerHTML (-> (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).
(set! (.-innerHTML (-> (js/document.getElementsByTagName "h1") (aget 0))) "Equivalent one-liner wihout 'let'?")
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
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. 😉
well as I said there are many ways to write this. so the most important step is learning what every part does.
(-> (js/document.getElementsByTagName "h1") (aget 0) (set! -innerHTML "Equivalent one-liner wihout 'let'!"))
also worksGood 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).
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!
js/document.getElementsByTagName
returns an array, aget
gets the nth element of that array
js/document.getElementById
only returns a singular element, not an array
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).
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.
you can ignore that one. you can create externs for module
to get rid of it but it is safe to ignore
thanks
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.
(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!)
@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.
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
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.
definitely shows that we need a lot more documentation for all of this 🙂
or a #shadow-cljs-beginners kiddie pool. 😉
its fine to ask here. I'll answer when I have time.
I think the current documentation is extremely good, but it's written in a style that makes it difficult to consume
i've been actually planning to propose an alternative presentation for it, or a kind of rewrite
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
@henryw374 from the clojure REPL (shadow/watch-set-autobuild! :the-build-id true|false)
no clue if anyone ever actually used that or if it works but I added it a long time ago 🙂
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
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"}}
so, for each module a single .js
file is generated
I get this error when I don't add :depends-on
ExceptionInfo: two modules without deps, please specify which one is the default
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
actually, I think I might have figured this out... the documentation helped
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
just :shared {:entries []}
and then all the other :depends-on #{:shared}
they are all written to the output-dir, no need for :output-to
per module
thanks
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
yeah all that stuff is extremely messy
https://clojureverse.org/t/new-build-reports-with-dependency-traces/7653
so nobody ever has to ask again why cljs.pprint
was in their build 😉
Thank you so much for doing this