Is there some helper in shadow-cljs for adding a hash to a filename? I'd want to add a hash to my shadow-css generated css file as well
https://shadow-cljs.github.io/docs/UsersGuide.html#NameHashing
I personally use a unique output dir instead of hashing actual filenames. :output-dir "public/js/v1.3" or so
Thanks! I've been able to set the javascript compile up following that, and adding shadow.html/copy-file as a hook it replaced the filename in the html as intended.
What I'd like to know is how to achieve the same with a shadow.css build Is there some helper to add the hash to the filename? How am I supposed to call the copy-file hook from the css build clj?
you don't need to call the copy-file hook at all ever
I trust that you can generate some html by yourself. so the question then becomes where do you get the data
I have a static index.html
for the shadow-cljs part a manifest.edn is generated in the :output-dir, which you can (read-string (slurp "public/js/manifest.edn")) or so to get the data you need
even easier with a static file
there is absolutely zero reason for any of this to run as part of the shadow-cljs build/hook
I mean look at the code for the current hook, which I should have never created to be honest
https://github.com/thheller/shadow-cljs/blob/master/src/main/shadow/html.clj
its not doing much
yeah but not having to write it myself is still a nonzero gain
could you point me to where you inject the file hash into the filenames?
for that I suggest looking at the manifest.edn and printing it
you'll find a structure like [{:module-id :main, :name :main, :output-name "main.js", ...
:output-name in this case will contain the hashed name
I'd need to inject the hash similarly into my shadow.css css file name as well so any pre-existing infra is helpful. I don't think my css build script would write into the manifest.edn or would it?
so the copy-file hook just replaces /js/foo.js with /js/foo.<hash>.js
shadow.css builds are by design a clojure function. you can modify it however you like
for example currently in your build you will have a write-outputs-to call
a trivial function to start with https://github.com/thheller/shadow-css/blob/3bb029558e91223a5dff55f17b9514d65f399e1e/src/main/shadow/css/build.cljc#L528-L537
so you just write your own that injects a hash
there is currently nothing built-in for this
I think I've found a problem on how :dev-http handles classpath files. I have a deps.edn with :paths ["src/clj" "resources" "target/classes"], in my shadow-cljs.edn I have :dev-http {8280 ["classpath:public"]} and in a build configuration I have :output-dir "target/classes/public/js". When my repo is in a clean state (the target/ directory doesn't exist yet) the dev-http server won't serve the target/classes/public directory that gets created after the server starts. If I kill the shadow-cljs server and start it again (now that the directory exists and is populated) everything works fine and dev-http server happily serves the resources in that directory
not really a shadow-cljs problem
classpath is a set of paths, so it is not possible for shadow-cljs to know that classpath:public was supposed to be target/classes/public, might as well have been src/main/public as far as its concerned
you are right
is it possible that dev-http server, looks at the available public directories in the classpath and populates a file search path for them only on startup?
FWIW just use target/classes/public instead of classpath:public
don't understand what you mean by "file search path". basically if a request comes in for say /index.html it'll look for public/index.html ANYWHERE on the classpath. in any dir plus any .jar
So, this change works:
:dev-http
- {8280 ["classpath:public"]}
+ {8280 ["resources/public" "target/classes/public"]}that lookup is entirely outside the control of shadow-cljs, it uses the standard JVM lookup mechanism
yes, for regular dirs shadow-cljs will create them when launching
I'm just curious why the first one did not work because:
(-> (System/getProperty "java.class.path") (clojure.string/split #":") (->> (remove #(clojure.string/ends-with? % ".jar"))))
; --------------------------------------------------------------------------------
; State: clj
; eval (current-form): (-> (System/getProperty "java.class.path") (clojure.string/...
("dev/clj"
"dev/cljs"
"test/clj"
"test/cljs"
"src/cljs"
"src/clj"
"resources"
"target/classes"fairly certain the JVM just ignores any directory that doesn't exist and doesn't actually add them to the classpath loader thing
nop, just confirmed this is not the case in #clojure
or yeah it could be an internal jvm thing
clj -Sdeps '{:paths,["foo"]}'
Clojure 1.12.0
user=> (require '[clojure.java.io :as io])
nil
user=> (io/resource "foo.txt")
nil
user=> (def f (io/file "foo" "foo.txt"))
#'user/f
user=> (io/make-parents f)
true
user=> (spit f "foo")
nil
user=> (io/resource "foo.txt")
nil
user=>
clj -Sdeps '{:paths,["foo"]}'
Clojure 1.12.0
user=> (require '[clojure.java.io :as io])
nil
user=> (io/resource "foo.txt")
#object[java.net.URL 0x64711bf2 "file:/Users/thheller/code/tmp/foo/foo.txt"]til
I'll change shadow-cljs :dev-http to use specific paths then, thank you!
well the correct solution would be to not use directories that don't exist as classpath entries š
it doesn't actually matter that target/classes/public doesn't exist. that will be created and used. it matters that target/classes doesn't exist
if it won't exists half the time it shouldn't be in :paths if you ask me
yes I was thinking of creating the directory before starting the shadow-cljs server, but adding it to the dev-http paths is more elegant
yes I was fairly conflicted about this too
for me its more a matter of correctness than elegance š
on one hand I would love to have all 'build' state in a single dir like target/ so that repo cleanup is straightforward
on the other hand i'm not sure how I should serve compiled/generated cljs sources from this directory that might not exist
I think the answer is to remove the target/classes from the classpath, and use a dedicated output directory in target/ for cljs
and when building the uberjar copy them to the resources target
i need to analyse typescript syntax and parse the import statements, anyone know of any clojure code that does this?
If you prefer correctness, Iād call into Babel parser or some internal packages of TS to spit out AST as json
I would also be surprised if there's no tree-sitter solution available, but if you just want the imports and don't really need proper analysis; you would be better of by just parsing the head yourself.
there should be plenty JS tools that already do this, for clojure/java I don't know of any