thheller / shadow-css

CSS-in-CLJ(S)
https://github.com/thheller/shadow-css
Eclipse Public License 1.0
108 stars 10 forks source link

Unique class names #20

Open philjackson opened 10 months ago

philjackson commented 10 months ago

This will make class names unique according to the rules and only put them in the CSS once. To make up for losing the usefulness of having the ns line/num in the name, I've started printing them in the output which gives this sort of thing:

/*
example.frontend.pages.dash 10:11
example.frontend.components.toast 17:29
example.frontend.pages.person 11:9
*/
.sc-729220566 {
  background-color: #fda4af;
}

My concern is the use of hash and just how consistent it is everywhere, however, I've tested it across different architectures and clojure versions and the output seems to be the same.

thheller commented 10 months ago

Interesting, but I don't think this is the way to go as an optimization strategy.

For example I ran this to generate the shadow-cljs UI css. While the resulting file is a bit smaller before gzip, it is actually about the same after gzip. 5525 bytes before, 5573 bytes after. brotli is similar. So, we actually gained a few bytes and lost any possible debuggability. hashes in general are pretty terrible for compression, so the HTML/JS side probably looks similar when it comes to raw gzip bytes. This was using a "minified" version, so all comments were stripped.

My plan for optimizing build sizes was using active class name replacements. For CLJS this can actually be done at compile time, for CLJ that would be handled by this atom.

https://github.com/thheller/shadow-css/blob/b3c97fe3caf16fab1a90fb93a7baad76fe15aa46/src/main/shadow/css.clj#L6-L7

Basic idea is to generate a "manifest" when building the CSS, populate the atom with it and use the replacement names. So, basically {whatever_foo__L2C8 "a X"} or so.

What this enables is that actual combinations can be created and reused. Say you have padding: 10px in 15 different rules, you could pull it out into its own rule instead of repeating it 15 times. Just make the resulting classname a combination of one or more, and while we are at it lets also shorten everything, so it might become a X, important bit being that the name can be changed and use more than one rule.

Given how well the current style compresses this hasn't seemed like a high priority so far, so have not spent any time on it. I have seen other tools use this strategy, but no data on how well that actually performs.

I'll think about the hashes for a while, but no promises this will be merged.

What I might be open to is "finishing" the manifest generation and then let a "customizable" mechanism optimize that, so you could just generate {whatever_foo__L2C8 "sc--123123"} and end up with the same results.

philjackson commented 10 months ago

No worries, @thheller. Thanks for taking the time to look at it.

Out of curiosity, was there much reuse when you ran it against shadow?