shadow-cljs

https://github.com/thheller/shadow-cljs | https://github.com/sponsors/thheller | https://www.patreon.com/thheller
FHE 2021-05-06T06:16:44.312100Z

Hi everyone. Painfully noobish CLJS-er here. Just wondering why when I created a project folder with the npx command near the beginning of the shadow-cljs user guide....there is no main.html file I can find.

thheller 2021-05-06T06:27:54.312600Z

@factorhengineering if you continue reading the README it is telling you to create it?

FHE 2021-05-06T06:39:41.314400Z

@thheller I haven't read the whole thing yet, but I would have thought it would be a basic thing any project would need, so it would be created at the beginning.

thheller 2021-05-06T06:43:54.317100Z

the npx create-cljs-project only generates the very bare bone project skeleton. I don't know what you are going to build. might be a node script, might be a react-native app, might be browser-based app. not all of them require html files.

FHE 2021-05-06T06:43:56.317300Z

I did just search for main.html, and index.html (I think that's what I meant in the first place), but I don't really see a step of creating one. ...and again, isn't it needed for CLJS?

thheller 2021-05-06T06:44:25.318Z

you can use a more specific templates like the re-frame template if you like. that generates a HTML file

FHE 2021-05-06T06:45:12.319Z

A react-native app wouldn't need one? Wow. OK, it does not work the way I thought it would. I thought react native just ported a standard JS-enabled webpage to mobile.

thheller 2021-05-06T06:45:24.319200Z

no it does not. that would be something cordova and others do.

FHE 2021-05-06T06:46:29.320300Z

My dream of making an app that works on web and mobile is looking ever more distant. lol A widening gulf of learning between me and it. Haha

thheller 2021-05-06T06:47:05.321100Z

well there is react-native-web that turns a react-native ab into a webapp but thats about all I can tell you about it. never used it myself.

FHE 2021-05-06T06:49:18.323200Z

Input mobile app, output webapp?? That's backwards from what I'd heard so far. OK, I wasn't going to worry about mobile just yet...focus on web...but based on that maybe I should jump right in. 😕

FHE 2021-05-06T06:49:40.323700Z

Will have to decide tomorrow. Too tired now. Thanks for your help. 🙂

SignSpice 2021-05-06T06:53:43.325Z

Hello, I am curious if it is possible to get a shadow-cljs repl connected to a browser userscript.

thheller 2021-05-06T06:55:12.325200Z

define "browser userscript"?

SignSpice 2021-05-06T07:01:28.328900Z

like a GreaseMonkey script. (Or in my case, VionlentMonkey).

thheller 2021-05-06T07:02:08.329900Z

I don't know to be honest. if they can open websocket connections and eval then in theory sure you could do it

Rob Knight 2021-05-06T07:02:19.330400Z

Firebase recently released a beta of their JS SDK which is designed to support tree-shaking and thus reduce bundle size. However, it doesn't seem to work! Replicating their JS code, I've translated import {getAuth} from "firebase/auth" as ["firebase/auth" :refer [getAuth]], which should import only that function. Instead it seems that everything is being imported, as it was in the previous (non-tree-shakeable) version. Is there anything else I ought to be doing here, or is this a case of Closure compiler not being able to use the same strategy as Rollup/Webpack would?

thheller 2021-05-06T07:02:21.330500Z

but I don't know enough about how they work at all to be sure

thheller 2021-05-06T07:03:06.331200Z

yes, that kind of "tree shaking" currently refers to something only js tools do, not the closure compiler

Rob Knight 2021-05-06T07:04:18.332700Z

Ok, thanks!

SignSpice 2021-05-06T07:04:44.333200Z

They are pretty simple in that they more or less just inject a javascript file into a given webpage as if that webpage loaded it. Like a content script in a browser extension, except without the security restrictions. (IE. Eval works).

thheller 2021-05-06T07:08:10.333500Z

so in theory you can just make a normal :browser build

thheller 2021-05-06T07:08:39.334200Z

and then manually inject a &lt;script src="<http://localhost>:port/script.js"&gt; into the page from the script

thheller 2021-05-06T07:09:10.334700Z

might need to tweaks some stuff like :asset-path and :devtools-url though

thheller 2021-05-06T07:09:21.335Z

never tried it but might work

SignSpice 2021-05-06T07:12:02.336100Z

Okay, thanks! I'll look into it more and see if I can figure it out.

Jakob Durstberger 2021-05-06T07:35:47.337800Z

Does anyone know what is wrong with the following snippet?

(ns main
  (:require ["@aws-sdk/client-dynamodb" :refer [DynamoDBClient ListTablesCommand]]))

(DynamoDBClient. #js {:region "eu-west-2"})
The error I am getting is: shadow.js.shim.module$$aws_sdk$client_dynamodb.DynamoDBClient is not a constructor I translated this from https://www.npmjs.com/package/@aws-sdk/client-dynamodb
import { DynamoDBClient, BatchExecuteStatementCommand } from "@aws-sdk/client-dynamodb";

const client = new DynamoDBClient({ region: "REGION" });

thheller 2021-05-06T07:38:26.338200Z

looks fine

thheller 2021-05-06T07:38:48.338600Z

try adding an :as to the :require and logging that to see what it is

thheller 2021-05-06T07:39:20.339100Z

also check that there are no other errors during load

thheller 2021-05-06T07:39:48.339600Z

aws has in the past written code that only worked with webpack, might be the case here too

thheller 2021-05-06T07:40:00.340Z

can't help further though, gotta go

Jakob Durstberger 2021-05-06T07:40:28.340600Z

> also check that there are no other errors during load I didn’t restart the REPL after adding new dependency 🤦 Thank you

Mikko Harju 2021-05-06T09:05:22.341700Z

Hi! What would be the best way to access goog-defines (or any other setting if this is not feasible, defined in shadow-cljs.edn) in macro context to prevent generating code if a flag is set?

Mikko Harju 2021-05-06T09:25:02.342Z

Answering myself: (get-in @env/*compiler* [:options :closure-defines])

FHE 2021-05-06T12:48:57.345500Z

Given that the project structure created by running `

npx create-cljs-project my-project
does not include any index.html` (or a folder for CSS, as far as I can tell), how should I add it? I mean where? Somewhere in the project folder? If so, then do I need to add any pointer to where it is anywhere? And would I need to manually have it point it at wherever my main output JS file is for a given build (test vs develop vs release)?

thheller 2021-05-06T16:16:25.346200Z

@factorhengineering the readme covers this https://github.com/thheller/shadow-cljs#quick-start css files you just put somewhere in the public folder and use link it from the HTML.

FHE 2021-05-06T18:08:08.349300Z

@thheller Thank you! I had been combing through the larger https://shadow-cljs.github.io/docs/UsersGuide.html but couldn't find it there. So I guess none of the automagic goodness really touches the .html file(s?) or .css file(s), and where things get put doesn't really matter other than making sure the normal linking in the index.html file (to the .css and to the .js file, where the name of the .js file would be whatever the compilation output is) is correct? Fair enough. 👍

thheller 2021-05-06T18:27:51.350400Z

css is not related to js in any way. they both just get included in the html and do their stuff

thheller 2021-05-06T18:28:18.351Z

shadow-cljs doesn't handle generating/compiling css in any way but it does offer some basic hot reloading if you modify the file

FHE 2021-05-06T19:02:51.352700Z

...but the location of the .css files don't matter because shadow-cljs knows where they are based on the reference in the index.html file? OK, great. I'm probably just make a css folder under src for projects where I use CSS.

thheller 2021-05-06T19:04:21.353500Z

seems like you misunderstand how this works

thheller 2021-05-06T19:04:28.353700Z

I said "public" not src

thheller 2021-05-06T19:04:56.354400Z

the public folder is the folder served by the web server, so all files in that (including subdirectories) are reachable via http

thheller 2021-05-06T19:05:24.355Z

so you create public/css/foo.css and link it in your html via &lt;link rel="stylesheet" href="/css/foo.css"&gt;

thheller 2021-05-06T19:06:39.356200Z

if you intend to build css using other tools that is fine, but shadow-cljs only cares about the final file in the public folder

thheller 2021-05-06T19:06:50.356500Z

how it got there is not relevant as far as shadow is concerned

thheller 2021-05-06T19:07:26.356900Z

but all of this is basic html/css stuff, it has absolutely nothing specific to do with shadow-cljs

thheller 2021-05-06T19:15:02.357800Z

the path you use is also completely up to you, as long as it is in the public folder it doesn't matter

thheller 2021-05-06T19:15:38.358800Z

that isn't even shadow-cljs caring about it at all, its the browser needing to load it over http and only seeing what is in the public folder

thheller 2021-05-06T19:15:45.359100Z

or whatever other webserver you intend to use

FHE 2021-05-06T19:17:50.360500Z

I do understand those basics. I was just wondering where those basic files go (after getting over my initial shock that they weren't auto-generated for the project), and yes I thought maybe those basic files got acted on in some way by the tools.

thheller 2021-05-06T19:18:47.361200Z

well for hot-reloading it basically just watches css files in the public folder and reloads them on change, but that is the only thing shadow-cljs does regarding css files

FHE 2021-05-06T19:21:59.362Z

I can't even find a public folder. I guess I need to make one myself under src?

thheller 2021-05-06T19:24:22.364100Z

again .. the readme covers this ...

dpsutton 2021-05-06T19:24:55.365100Z

https://github.com/dpsutton/asg-ignite-presentation here's a presentation i did that has a walkthrough and a sample app with shadow if you think that might help

Franklin 2021-05-06T19:25:21.366200Z

Hello... would it be possible to use shadow-clj with a backend server that runs on the JVM? I have looked through the documentation at https://shadow-cljs.github.io/docs/UsersGuide.html#dev-http but cant find a good answer to this

thheller 2021-05-06T19:25:30.366700Z

the public folder is not under src, it is in your project root

thheller 2021-05-06T19:26:13.367500Z

sure, just run it separately. shadow-cljs doesn't care which server you use and the server doesn't need to do anything special. just serve the files from disk

Franklin 2021-05-06T19:31:53.370600Z

thanks

FHE 2021-05-06T19:33:37.371800Z

There's no public folder right now, so I guess I have to create it there. So in the root? OK. Scrubbing through the longer guide (Users Guide), I see lots of references to things being output to /public/js/ or /public/css/, but no reference to what the parent folder of public is, or of any files needing to be put there manually. I do see the part about setting the watchdir to public (which I guess I'm supposed to assume is my-project/public?) in order to have CSS reloading. ...but then there's a part about testing that mentions /resources/public/js/test/, which looks like a public folder not in the root. Actually the example given in the early 1.4.3 "Convensions Used" section mentions resources/public/js/ as well. Sorry just trying to wrap my head around this.

thheller 2021-05-06T19:35:00.372500Z

all paths mentioned are always relative to the project root, the folder your shadow-cljs.edn is in

thheller 2021-05-06T19:35:56.373400Z

you incorrectly added a leading /, you may use that but that would make it an absolute path outside your project folder

FHE 2021-05-06T19:36:30.374100Z

Just trying to indicate folder. I guess that's obvious. I can drop those first and last slashes.

thheller 2021-05-06T19:37:23.375300Z

the leading slash is very important when talking about this stuff, so it does matter whether it is there or not

FHE 2021-05-06T19:37:34.375600Z

Did not think it would be an absolute path without a drive or net location at the beginning, though. Maybe it's a Linux thing? It assumes /a/b/c means ~/a/b/c ?

thheller 2021-05-06T19:37:59.376100Z

an absolute path is an absolute path in your filesystem root

FHE 2021-05-06T19:38:17.376800Z

I mean (whateverdrive)/home/a/b/c

thheller 2021-05-06T19:38:18.376900Z

so /public/js would be c:\public\js on windows or just /public/js in linux

thheller 2021-05-06T19:38:37.377300Z

and no /a/b/c does NOT mean ~/a/b/c

FHE 2021-05-06T19:38:44.377900Z

OK, so not even home. Root of the whole drive. Got it.

Franklin 2021-05-06T19:41:36.379800Z

@thheller if I'm serving the compiled JS files from my own server.. do you think hot reloading will still work?

FHE 2021-05-06T19:41:39.380Z

In @dpsutton's presentation I see reference to folder public, which I now get is my-project/public. So I should ignore the other kind of example from the User Guide, with resources/public?

Franklin 2021-05-06T19:42:46.380900Z

I don't think so, but I'd like to hear what you think

thheller 2021-05-06T19:43:16.381600Z

thats just another folder, your config decides which folders you use. those names are YOUR choice, name it whatever makes sense for you. I use public everywhere. other people prefer resources/public. others use dist, target, web or whatever else may fit

thheller 2021-05-06T19:44:29.382Z

it just works. hot-reload is not dependent on the server that served the files. that is handled by the websocket connection the compiled code opens, which will talk to the shadow-cljs watch server directly

👍 1
thheller 2021-05-06T19:45:38.383500Z

as far as your webserver is concerned there are just some static .js files on disk somewhere that you expose via http

Franklin 2021-05-06T19:46:26.384600Z

alright, thanks again

FHE 2021-05-06T19:46:41.385Z

OK. I'll stick with that. So at any point does that get duplicated? I have hit upon the concept of shadow-cljs having multiple targets. I would guess the index.html file in public gets used for a web release (and test?) but there is some kind of other output for, say, mobile or desktop(/server)?

thheller 2021-05-06T19:48:01.385700Z

that all depends on what you are building. as I said before if you build a react-native app or a node-script those will not have html files at all

FHE 2021-05-06T19:50:12.387900Z

OK maybe what I'm talking about only makes sense for dev vs release vs test. 1 of those uses the 'real' original index.html, and the others use some kind of auto-duplicated one? I only suggest that because I think I saw something like that in the guide. If there is only ever the one file, well I'm happy to be wrong because that would be simpler.

thheller 2021-05-06T19:51:13.388200Z

no, shadow-cljs will never duplicate any html for you

thheller 2021-05-06T19:52:08.389100Z

and again .. that entirely depends on what you are building. I pretty much always have a CLJ server generating my HTML for me, so I never have a static index.html on disk anywhere

thheller 2021-05-06T19:52:40.389800Z

and my dev html I have is identical to the release html in all cases

FHE 2021-05-06T19:53:42.390400Z

Oh right...hiccup? Yes, another thing I need to learn how to set up.

thheller 2021-05-06T19:54:22.391500Z

well I also have a really old rails app generating some HTML, doesn't really matter where the html is coming from

FHE 2021-05-06T19:54:30.391800Z

It does sound like there are multiple copies of index.html, though. If not auto-generated, then at least put in place manually for the different web targets if there are more than one.

thheller 2021-05-06T19:55:03.392400Z

if what you are building requires multiple html files then you'll have multiple html files yes

FHE 2021-05-06T20:10:27.394300Z

• I meant multiple copies, just based on the following from the User Guide: • "Remember that the test directory will have the index.html, and a js folder." and • "https://shadow-cljs.github.io/docs/UsersGuide.html#_generated_output_in_code_test_dir_code`:test-dir` The output includes two primary artifacts in your test-dir folder: index.html - If and only if there was not already an index.html file present. By default the generated file loads the tests and runs init in the :runner-ns. You may edit or add a custom version that will not be overwritten.

FHE 2021-05-06T20:11:07.395Z

...but I'm happy to ignore that possibility for now. I'm a long way off from doing specific test builds I would think.

FHE 2021-05-06T20:28:53.408800Z

Thank you for your help. As painful as it might have been for you to realize a person out there doesn't know this already by the way, I'm really glad our conversation meandered into Linux folder reference convention. I've done some things in Linux before and am still surprised that /x/y/z could ever be considered an absolute path when it doesn't mention a drive (and when it differs so little from x/y/z), like C:/x/y/z .

FHE 2021-05-06T20:30:21.409800Z

Maybe I'm a strange case, but I would suggest actually adding that to https://shadow-cljs.github.io/docs/UsersGuide.html#_conventions_used . (i.e. "References to folders in this book (as in many types of code (html/css/js/...) are usually relative and of the form folder-x or folder-x/subfolder-y which indicates the parent of the top folder referred to (folder-x in both cases above) is the root project folder.")

FHE 2021-05-06T20:32:32.411800Z

Even more helpful would be throwing in some early info on index.html, i.e. right under the npx command in https://shadow-cljs.github.io/docs/UsersGuide.html#_standalone_via_code_npm_code`npm`the text could be expanded to "This will create all the necessary basic files and you can skip the following commands. Note that index.html is not considered a basic file, and for projects which would need one (web projects), it will need to created manually. A popular practice is to also create a 'public' folder in the project root folder and create the index.html there. Any css files would also need to be created manually (or by some other method outside the scope of this book), and could be put in a new folder public/css ."

thheller 2021-05-06T20:33:01.412400Z

I think you have the wrong expectations here

thheller 2021-05-06T20:33:36.413700Z

there are far better guides/tutorials and even video courses to teach you specific things. like building a web focused thing

thheller 2021-05-06T20:34:19.415200Z

shadow-cljs is just a generic build tool that can do many things. I cannot possibly cover all of them, I simply do not have the time to do so

thheller 2021-05-06T20:35:10.416300Z

https://github.com/day8/re-frame-template for example gets you a fully running web thing out of the box

thheller 2021-05-06T20:35:31.417Z

create-cljs-project by intention is minimal and does NOT provide and target specific things

thheller 2021-05-06T20:35:48.417600Z

there are simply too many options, I cannot cover them all

FHE 2021-05-06T20:35:50.417700Z

Like I said, I fully admit I don't have the same background knowledge of many or even most other readers of that guide, but I'd like to think it was not completely crazy of me to assume that 'all the necessary basic files' for a CLJS project would include index.html and maybe even a single .css file. 😉

FHE 2021-05-06T20:36:33.418100Z

I mean I know that was wrong now, but... Haha.

thheller 2021-05-06T20:38:29.419200Z

there is also https://github.com/filipesilva/create-cljs-app which maybe better suited for your needs, that also generates much more web centric stuff (including html and css 😉)

FHE 2021-05-06T20:40:38.421300Z

Your first link scares me a bit, what with needing leiningen (I thought I heard using shadow-cljs would mean not needing to also use leiningen) and node.js (I thought...still think actually...node.js was for server-side/desktop, but maybe it's there because it generates front-end and back-end.

thheller 2021-05-06T20:41:19.421700Z

you already used node.js when you executed npx create-cljs-project

thheller 2021-05-06T20:41:30.422Z

npx is part of npm which comes with node

thheller 2021-05-06T20:43:09.423300Z

you don't need to use leiningen, but some people prefer to do so. so some templates use it, many also use deps.edn. those are all valid options, as I said ... impossible for me to cover them all

FHE 2021-05-06T20:52:04.427100Z

Same with re-frame, actually. I was trying to minimize the number of new things I need to learn at once (WSL2 + Linux CLI + Doom Emacs (vi) + CLJS + <some build tool, which I chose to be shadow-cljs based on recommendations based on it being able to handle a lot>), but I accept your challenge of adding re-frame to that soon. 😎 I'll lean toward deps.edn over leiningen, though, just since it seems simple (just an actual file).

FHE 2021-05-06T20:52:19.427600Z

I'll dive into your second link even sooner, though. Thanks again.