Skip to content

A minimal repro for getting a shadow-cljs project small

License

Notifications You must be signed in to change notification settings

staab/shadow-tiny

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

5 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Build with npx shadow-cljs release library

Get size with ls -la build | awk '{ sum += $5; } END { print sum; }' "$@" -h build. Currently this gives me 25133, which is pretty much the size of cljs.core, trimmed down a bit by tree-shaking.

My chat log with @dnolen and @thheller explains why this is the case, and why it can't get much smaller:

jstaab [9:12 AM] Hey there, I'm trying to optimize my bundle with shadow-cljs, in particular by trimming down cljs.core as much as I can. I've got a reproduction of just a small proof-of-concept here: https://github.com/staab/shadow-tiny

The problem I'm running into is that if I use anything in core, my bundle blows up in size; currently I'm just invoking a couple core functions, and the size of cljs.core.js alone is 97k. Is there any way to improve this? I was thinking of maybe using refer-clojure in all my namespaces, but the docs say "The only options for :refer-clojure are :exclude and :rename". I'm also not sure if this would work, because it does appear that google closure compiler is properly tree-shaking things (cljs.core.js is only 1.1k if I remove the body of my main function, and my other project's cljs.core.js is 136k). (edited)

lilactown [9:22 AM] have you used the shadow-cljs build report? it can give you better insight into what’s taking up space

jstaab [9:23 AM] I haven't on this project; I tried it on my main one yesterday and it crashed so I moved on let me give it a quick go

lilactown [9:23 AM] that might a good thing to report if you have the time

jstaab [9:23 AM] This is my source code though:


(defn ^:export main []
  (print (map inc [1 2])))

lilactown [9:24 AM] I think what you’re going to run into is that the CLJS data structures weigh about 60-80kb un-gzipped

jstaab [9:25 AM] Ok, so I guess there's just not really a good way to avoid that Is there a way to use a CDN for cljs core?

lilactown [9:25 AM] no, because it will tree-shake and remove things you don’t want if you used a CDN for cljs.core it would be even bigger

jstaab [9:25 AM] Bigger, but hopefully aggressively cached Preact/redux are a total of 5k (gzipped), and I'd like to get cljs to compete with that somehow it looks like my toy project is 88k gzipped Is there any prior art on this you know of? I haven't been able to find any articles about tiny bundles online

lilactown [9:27 AM] preact and redux are much smaller in scope than CLJS (the language) it’s comparing apples to oranges

jstaab [9:28 AM] It's true, but as far as delivering something to users, I'm more willing to suffer with js than bloat my bundles

lilactown [9:29 AM] for perspective, immutable.js is ~64K minified

jstaab [9:29 AM] ouch Man, I love immutable data structures, but I'm not sure they're worth the cost

lilactown [9:30 AM] I think they are 🙂

jstaab [9:30 AM] heh

lilactown [9:31 AM] 88K is honestly not enough that I would start to balk. that’s not going to strain my users

jstaab [9:31 AM] hmm I think I'm misusing du too, it should be smaller than that (edited) ls gives me closer to 35k (edited)

thheller [9:33 AM] @jstaab CLJS isn't really suited for "tiny" bundles since you are always going to end up with cljs.core and the datastructures its never going to compete with preact/redux (edited)

jstaab [9:34 AM] @thheller thanks for the confirmation, that's what I was beginning to suspect

thheller [9:34 AM] but it'll easily beat preact/redux/immutable/lodash which you are basically getting with cljs.core

jstaab [9:34 AM] do you have any strategies for alleviating the burden? I'd love to use it everywhere, and with cljs.core aggressively cached on a CDN that seems feasible (edited)

dnolen [9:36 AM] there's really not much more you can do

thheller [9:36 AM] use code splitting .. but no CDN caching cljs.core is not possible

dnolen [9:37 AM] code splitting is the answer if you want to limit the initial payload - but fundamentally we start around 22K-25K gzipped and go up from there given modern JS development - we are in fact very light weight

jstaab [9:37 AM] CDN caching is not possible meaning not supported/worth supporting, or is there something more fundamental going on with how it's linked?

dnolen [9:37 AM] and not really interested in investing more time beyond what Closure gives us

jstaab [9:37 AM] Ha @dnolen I've been reading some Henrik Joreteg lately and it's inspiring me to change that

dnolen [9:37 AM] sure but I don't really sympathize that much with such efforts - Closure fundamentally does the only interesting thing that can be done the only JS project that understands this is Rollup hand optimizing payloads is a massive waste of time IMO

jstaab [9:40 AM] I buy that for sure Cool, thanks all for the answers, that was super helpful

dnolen [9:43 AM] Svelte is also interesting - but I can't find any data on that on really large projects but my hunch is once you factor in all the dependencies you actually need, internationalization etc.

jstaab [9:43 AM] Svelte is interesting

dnolen [9:43 AM] it doesn't add up to much

jstaab [9:43 AM] yeah, I trimmed down my moment-timezone bundle yesterday

dnolen [9:43 AM] which is probably why don't find anyone bragging about non-toy stuff

jstaab [9:43 AM] saved me 800k

dnolen [9:44 AM] so suffice to say, I think ClojureScript and Closure are still state of the art, the real answer is make sure deps can be dead code eliminated I think ClojureScript core is like 75,000-80,000 lines of generated JS or something (edited) and you get 22K gzipped as the starting point

jstaab [9:45 AM] Yeah, that makes sense If there were fewer macros, would bundle sizes shrink? I suppose run times would grow commensurately though

thheller [9:45 AM] macros don't contribute to bundle size at all

dnolen [9:46 AM] macros don't contribute

jstaab [9:46 AM] Really? I thought they were evaluated during build time, so if I had (defmacro x [] "blah blah blah") and used it a bunch, wouldn't the output be bigger? Or do you mean it's just negligible?

thheller [9:47 AM] the code they generate end up in the JS. the macros themselves don't. (edited) so yeah if you generate a bunch of code they can affect the bundle size if emit the same stuff over and over again

jstaab [9:49 AM] I see what you mean, the output would be the same whether you used a macro or manually wrote everything out longform, unless your macro is bloating the output unnecessarily Anyhoo, thanks for your time, both of you

dnolen [9:54 AM] @jstaab right and if you don't use it, it will still get eliminated from the final build

About

A minimal repro for getting a shadow-cljs project small

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published