This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2023-07-05
Channels
- # announcements (5)
- # babashka (2)
- # beginners (47)
- # calva (3)
- # cider (42)
- # clerk (5)
- # clj-commons (21)
- # clojure (145)
- # clojure-austin (25)
- # clojure-europe (14)
- # clojure-norway (9)
- # clojure-spec (7)
- # clojurescript (21)
- # datomic (4)
- # dev-tooling (4)
- # docker (5)
- # gratitude (5)
- # honeysql (6)
- # hyperfiddle (45)
- # jobs (1)
- # juxt (2)
- # malli (25)
- # meander (1)
- # mount (3)
- # other-languages (7)
- # pathom (7)
- # pedestal (1)
- # reagent (5)
- # reitit (20)
- # releases (2)
- # remote-jobs (1)
- # shadow-cljs (77)
- # squint (8)
- # tools-deps (34)
is there a macro for eliding development code?
something like (shadow/when-dev <perform extra expensive validation>)
this sounds handy, thank you
and now I know what to look for I see it confirmed in the https://shadow-cljs.github.io/docs/UsersGuide.html too - awesome, thank you
(I guess I was hoping for a macro to elide the code completely, but this sounds close enough)
it's gonna be removed by Google Closure compiler as dead code, so not on Clojure level, but when generated JS gets compiled by Google Closure
ah, okay, well I guess that's exactly what i wanted then. thank you, I'd not appreciated that
I'm getting a lot of this during shadow compilation:
The body of an ES6 module cannot reference this.
The code works fine though. Any thoughts?I'm compiling TypeScript code to JavaScript that then gets consumed by ShadowCljs. Any code that has async stuff will get generated with code up to that looks like this:
the ts config targets ES6 because that's the only way I could get the imports to work 😅 and the thing to compile
I'll DM you
Also can anyone comment if this build for :app
looks correct (for purposes of including externs?) Ultimately I'd prefer to just include all the generated code as externs but I'm trying some hand written ones because I'm not sure how to programmatically include everything under the /src/js/gen
folder
note that :deps
is a top-level only key. it has no effect in the build config whatsoever
I wanted to include externs because things were getting renamed and I didn't want them to be
regarding the caching, I've been bitten enough times by not clearing out the .shadow-cljs
file that I turn off cacheing to try and prevent that from being an issue. Creates a more consistent experience across development environments
It's more like a superstition probably
neither have I cleared out .shadow-cljs
, nor should you. I mean I'm all ears if you have a reproducible problem, just not aware of any.
how do you include the JS? the :js-package-dirs
suggests (:require ["some-dir/that.js"])
, in which cases the code doesn't even run through :advanced
and externs will do absolutely nothing for that code
if its however included via (:require ["/some-dir/that.js"])
(i.e. absolute or relative path), then it might go through :advanced
(and you wouldn't need the :js-package-dirs
entry
@U05224H0W I use the (:require ["/path/to/js" :as js-code])
notation. I actually think what I'm seeing might be more a result of mixing "dot-attributes" and string access a little too carelessly. I try to use accessors when coding in typescript, but keywords when coding in clojurescript, and I think that I haven't been careful enough during serialization. At least that's where I'm at with it currently.
@U05224H0W no macro stuff. Actually I switched to TypeScript to avoid writing macros.
(:require ["/path/to/js" :as js-code])
is kind of dangerous. I don't really recommend doing that
Am I totally imagining things or is there a different way to use .cljc
besides a build hook or AOT compiling and putting it on the classpath?
Sorry, bad phrasing and not an area I'm too familiar with. Basically I am using some Java classes but couldn't require the code in a .cljs
file. But I used a macro and it works now.
I was working with javax.crypto
and the like, classes and APIs I know how to use. I don't know how to use equivalent functionality in JS so I did it in clj.
Does anyone have experience containerizing a cljs only, shadow-cljs project? Im trying to figure out how to correctly run shadow-cljs "in production" after building a release of my app. I've poured over the User Guide, and it seems like maybe running the watch is just the best/right way? The 'shadow-cljs server' command also seems to work, but gives the red warning banner about "stale output, is the watch running?". We are using shadow-cljs in conjunction with webpack if that makes a difference. Should i just be looking at how to run a client server only JS app in a container instead and leave shadow out after the release build?
sounds maybe like you're talking about a node.js/backend style project?
I'm just asking because there may be two senses of the word "server" here -- there is the shadow-cljs server (at least if you are targeting the browser), and then if you are making a server style application (aka with express
or something), that's something else
Ahh gotcha, yes to clarify im talking about the shadow-cljs server, to run our code in the browser. We have a webapp project, thats just shadow-cljs, no deps.edn or leiningen. Feel like we shouldnt need to build a whole uberjar for cljs code. I can copy the release build into the container of course, but it feels wrong to run a shadow watch as the container entrypoint, when we dont need the hot-reloader.
So are you serving the frontend code from the same server as the API/app server or those seperate concerns?
For instance, all my frontend code is separate from my backend code, so in my case, I can just run regular shadow-cljs watch dev
, and I just use some dev settings to configure the root URL of the API server I want to point to (and run the API server a different way, perhaps with a second shadow-cljs process or just a standalone node process)
oh wait I don't even do that, I just have the dev apis commented out and I just comment them back in lol
now if you server the frontend code as static files from the same server as the API server, then you need to configure some stuff in the shadow-cljs config
I was thinking of just serving them as static files, but it seems like there needs to be some kind of shadow server still running, since opening the index.html after a release build doesnt show the webapp as expected, just the 'reagent/ref-frame code goes here' splash screen
so this is a front end app only?
ok so if you check out my build above
I have :output-dir "resources/public/js/compiled/"
set
to test my code
I do shadow cljs release app
then in a terminal window, I navigate to resources/public
then I do python3 -m http.server 9500
then when you go to localhost:9500
in the browser, it should load up the index.html
located at resources/public/index.html
In the bottom of my index.html
, I have this:
<script src="js/compiled/app.js"></script>
that corresponds the the compiled code that should be in resources/public/js/compiled
(according to the :output-dir
setting)
in my <head>
tag, I load in the CSS as per normal:
<link href="css/screen.css" type="text/css" rel="stylesheet">
I use SCSS to compile all my CSS into a single stylesheet
so to be clear, that's how I TEST the production deployment, I don't use Python's simple server for production, I just stick the static files in cloud buckets and wire up the domain routes. You could do the same thing with Nginx or Apache on a traditional webserver, though
hmmm okay. maybe i just need a static webserver docker image to serve the compiled release app. my index.html has the same script tags to get to the compiled app.js as you. I just keep getting the static reagent/reframe splash screen instead of my compiled app code
did you make a custom index.html
?
<html lang="en">
<head profile="">
<meta charset="UTF-8">
<title>MyApp</title>
<link href="css/screen.css" type="text/css" rel="stylesheet">
</head>
<body>
<div id="app"></div>
<script src="js/compiled/app.js"></script>
</body>
</html>
should look something like thatnothing custom, it looks basically like that, plus more css lines and another script line for the webpack bundle. Nginx might just be the move, trying to get it working rn
yeah i was overthinking it, a static webserver docker image got it up. Wish the shadow-cljs reconnecting banner didnt show though
do you still have the shadow server running? Also might need to hard refresh to make sure you're getting the correct files if you're serving from the same port
I tend to go out of my way to make sure caches are purged before testing because I've been bitten by that enough times
I recommend reading a lot on paths since this setup is sufficient unless you want to use Node.js + SSR
my dockerfile is little more than having a "build" stage where I install java and node in alpine so I can npx shadow-cljs release app
, then run gzip and brotli on the outputted JS, and finally, in a "server" stage, copy the files over and launch nginx
this image then gets deployed to a kubernetes cluster (and since the frontend is trivially stateless + requires at most 5 MB of RAM, it suffices to have 1 replica and reserve most of your hardware for backend and microservices)
just to be absolutely clear: you do no NEVER run shadow-cljs in production environments. never ever, don't even think about it.