Another thing is splicing unecessary properties, which can even save more bytes, but given web apps becoming becoming so dynamic right now, that would be hard or really awkward for developer to work with too.
The programmer could shorten it when writing, but is the extra half a milisecond worth having to work with x, y and z as classes rather than more explicit classes?
If that's the case, using CSS Modules, you can do in CSS:
.list-1 { ... }
.list-2 { ... }
requiring it will yield a map like this: { 'list-1': 'JSNF4S12', 'list-2': 'IE945JSN' }
which you can use this way: const styles = require('file.css');
$('.' + styles[`list-${i}`])
// effectively $('.JSNF4S12')the other option is what CSS modules does. your scripts essentially "require" classnames from your stylesheets so as classnames in your stylesheet are minified so are their js references.
In fact this is how gettext() works.
CSS Modules [1] and other tools allow you to require CSS like you would with any other dependency, and replace named classes by unique hashes at build time. This prevents your CSS from leaking to elements that do not explicitly require it.
Note that perceptual hashes should not obey the avalanche effect, so a minor difference in the two images should yield a small change in the hashes (desirable in this case). Then accept results that are within some small % error margin.
An example of a library that does this is jimp [1].
[0] https://en.wikipedia.org/wiki/Perceptual_hashing [1] https://github.com/oliver-moran/jimp#comparing-images
Especially if media queries come into play and we'd have to try different resolutions and ensure they're all the same.
`gzip goodfile.css` and there's an improvement several times more effective than even the best minifier. And it keeps your source code legible in the browser and doesn't require a slow/buggy asset pipeline to test changes.
Yes, yes, I know minify+gzip can save like an additional 1% over what gzip alone does. To me, that's just not worth the cost to the developer.
Where I had to write and test a modal by scratch? That's a loss of time and money for no benefit.
>it keeps your source code legible
That's what Sass sourcemaps and source-beautifying browser plugins are for
>that's just not worth the cost to the developer
It's part of my build, it costs me nothing.
I generally share the opinion that most people using bootstrap probably don't need to. I'd recommend questioning it at the start of every project instead of assuming it's what a project starts with.
I think that while the described "reminification" method may not make sense in practice (as other's have said running minification process multiple times will amplify minifier bugs), Optimizing CSS, removing unused rules, grouping similar rules, optimizing selectors etc... does make sense, regardless of reduction amount in comparison to compression.
Some things can be over-engineered but under-scienced, so to say, at the same time.
A lot of great computer science already exists, and is applicable, and some of it is taught at universities. But it's not required for a CRUD app or for a flappy bird clone. And when you grow up enough to want more complex things, a lot is already forgotten.
I'm more a fan of writing compact, clean, logical css in the first place.
A couple months ago I worked on a project and re-wrote a 129k minified css file someone created as a clean un-minified 12k css file that had 100% of the original functionality plus some additional UI improvements.
You can only get these improvements if you understand what you are writing and stop using sass to write bloated files.
A minifier takes your css code and removes the noise from it. It does so by removing whitespace, comments, duplicate rules and redundant properties.
What it sounds like you're really complaining about is using sass (which has a compressed output), because it removes a layer of abstraction and makes it easy to shoot yourself in the foot. This is true of almost anything and everything.
Does your CSS completely lack whitespace and comments?
If not, minification still has its use.
I wouldn't recommend doing what the author suggests. crass doesn't squeak out extra bytes when you reprocess because it already does this for you.
If you combine multiple minifiers, the bugs in one minifier can end up being amplified by the others. For instance, one minifier might not consider !important when moving around CSS. Another minifier might then take that output and perform an optimization that's no longer just unsafe, but now incorrect. It might even delete rulesets that it believes are not used, ruining your stylesheet.
There are suites that test the correctness of minifieres, and many don't do great. CSS still "works" when the syntax is invalid, so invalid stylesheets result in undefined results when you minify. Between bugs and undefined behavior, I wouldn't recommend mixing and matching just to save one or two TCP packets, especially with gzip/brotli on the wire.
Your time would be far better spent, though, making a pull request to properly implement multiple passes on your minifier of choice so that you can safely get that benefit. Or you could say "meh, I'm not losing sleep over the extra hundred bytes" and work on something more productive.
I don't think there is one single use case, on any scale, anywhere in the world, where saving up to 17% on a minimized css file before gzip would matter in the slightest, let alone while adding 20mins to your build cycle :)
I'd call this half-satire. Half joke. Half thought experiment.
The idea is that you can run this once, benefit forever.
I'm myself in a need of a website that fits under 14K because I'm insane or something. Saving bytes might start to matter.
Now that also depends on what the TCP packet size is. For example saving 1Byte might not lessen the amount of network traffic needing to be sent.
"In short, if you try to eliminate redundancy by applying some kind of clever transformation or restructuring your data object before piping it to gzip, you will probably just do a crappy job of reimplementing gzip at the wrong layer of abstraction, and get worse results overall." -- https://github.com/wincent/relay/blob/hack/contrib/lightweig...
Also, your writing style is funny, nice work.
Stopped reading after this line.
The best part was that the whole description is technically correct.
It's a bit more complicated since you have to also vary the command line arguments you pass to the program. (Different color types can sometimes help, as can different filters.)
Something something entropy
It doesn't yet, but it could. Keep it mind, at the worst case scenario I get to pick which of the four individual minifiers I run. I will always at least be able to match the best one.
There is absolutely nothing that prevents me from running zopfli over the final outputs and comparing the sizes. I can use the compressed size to drive search. A matter of a change in metric used to consider what is an improvement.
I'll add this to my todo list on this project. Looks like I may be doing more on this than I originally intended...
Very nice, this is a fun project and a nice write up. I would definitely worry about lossy minification on production code, I've bumped into many minifier bugs that broke my valid CSS.
Also, pretty sure you could get Bootstrap.css down to a couple k-bytes and really truly pwn the file size leaderboard if you could dead-strip all the rules not actually referenced in your HTML & JS.
Most non-embedded CPUs are more than fast enough to decompress every bit they get from the network or disk without decompression becoming the new bottleneck. There are other factors like latency, seeking, the minimum block size, and it always depends on the application, but generally speaking reading and writing compressed data should always be considered.
That being said, for CSS the benchmark should rather be the size after gzip or other commonly used HTTP-Stream compressions, which are almost universally used anyway.
JS or HTML I suppose I could see, because they're more complicated, but CSS by itself is very simple, so I'm wondering what actually got left out.
Do you have any diffs or info on what it was removing or doing?
> Are the current CSS minifiers correct?
> I handle crashing minifiers, as well as ones that loop forever.
It could actually be useful to know the exact css before running the minifier who crashed/got stuck. One could check with a css validator if this is correct css in the first place (if not, one of the previous minifier screwed up) , and if so, inform the minifier's maintainers of their tool crashing with this particular valid input.
I was actually thinking this could be used to speed up computation a bit too. If you're going to add a set of minifiers to the end of the chain, caching the intermediate results (really just the last one) would let you avoid reprocessing from scratch each time you need to do cssnano | cssnano | csso | *, I don't know if it does this now but the description didn't talk about it either. That'd let you look at the chain and find where a mistake propagated from.
I will even learn CSS and JS to a degree where I can contribute the patches myself.
For example: consider a minified file x. X is likely getting gzipped when served. Is the reminified version smaller than the original? Same size? Bigger?
You might expect the obvious answer, but did anyone do the actual measurements?
This could even «minify the served CSS» a lot :)
(ok client side it will always be as big, but the server side is often paying its traffic and the client side may too so it reduces traffic anyway and means great savings).
For public static websites, the savings induced by gzip compression totally justify to not use http2 when traffic matters.
What do you mean? You can use gzip in HTTP/2.
#!/bin/bash
rm -rf $1
touch $1
to #!/bin/sh
>"$1"
Your turn, reddit $ ln -s /usr/bin/true ~/bin/cssmin
$ cssmin < in.css > out.cssThis is exactly backwards from what you want. You want the short strings to appear infrequently, and the longer strings a lot.
CSS resets sheets are a bad example for this kind of thing, as they're strongly sorted by desired output property, but for general CSS for something with a lot of components, for example, or a CSS sheet with page template specific styling, it seems like it should minify and gzip a lot better.
Plus, you can group your CSS by relevant section, i.e. keep your colours separate from your alignment, from your fonts, etc.
Except the problem is that doing it this way requires a bit of rearranging of the rules, which may cause some trouble in a fairly small number of cases, so that's why it's out as an automated way of minifying things.
I think I've decided it's obviously not worth it, even if we built a time machine and sent the css back to 1955 when they'd appreciate 261 bytes difference. (Granted they had no use for CSS in 1955).
If compressor1 generates the smallest result in step 1 all other compressors will only try to minimize this result. But maybe the compressor did something which the other conpressors are not optimized for. So you'll find a lically best solution for a starting point with conpressor1. But maybe it would have been better to start with compressor3 because it's result is smaller after step 2 than starting with compressor1.
Not to mention the author even admitted to not being very proficient in CSS and doesn't even want to learn JS because he "dislikes it too much"... The whole description of the process is basically dragging something on out of very little substance.
In general good laughing material though, just as he acknowledged at the end of the article, I guess.
Cool idea. Especially not reinventing wheels but chaining them together instead. Good work.
Now rewrite all your selectors in optimum precedence and specificity for file size. After that, remember that it will all go through gzip, so let's see how reordering properties affect compression.
I'm not, neat experiment though.
This article - I don't even...