Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Using zopfli to compress squeezes out 3 more bytes #12

Closed
davidmurdoch opened this issue Jan 16, 2018 · 8 comments
Closed

Using zopfli to compress squeezes out 3 more bytes #12

davidmurdoch opened this issue Jan 16, 2018 · 8 comments

Comments

@davidmurdoch
Copy link

The following outputs a file that is 395 bytes:

function css(done) {
    var postcss = require('gulp-postcss');
    var cleanCSS = require('gulp-clean-css');
    var cssvariables = require('postcss-css-variables');
    var zopfli= require('gulp-zopfli');
    return gulp.src('src/*.css')
        .pipe(postcss([cssvariables()]))
        .pipe(cleanCSS({ level: 2 }))
        .pipe(gulp.dest('dist/'))
        .pipe(zopfli())
        .pipe(gulp.dest('dist/'));
    done();
}
@ajusa
Copy link
Owner

ajusa commented Jan 16, 2018

Huh. I tried using Zopfli earlier, and it only got me another byte. I'll have to replicate this and see if it works on my end.

Thanks for bringing this up, it is very hard to drop bytes at this point!

@davidmurdoch
Copy link
Author

davidmurdoch commented Jan 16, 2018

Apparently zopfli is non-deterministic: google/zopfli#20

¯\_(ツ)_/¯

On my machine there are still some re-ordering of rules that will squeeze another byte or two out. I'm now a little tempted to create a brute-force CSS reordering gzip minifier thing to automate this step. :-)

@ajusa
Copy link
Owner

ajusa commented Jan 16, 2018

I actually wrote one of those already, that's how I got it down so small

@ajusa
Copy link
Owner

ajusa commented Jan 16, 2018

I was playing with Brotli, and got it down to 311 bytes.

I was able to get it down to 395 bytes with zopfli, and reordering. I'll probably switch to the zopfli number, and reorder for zopfli.

Brotli is gaining support though, so that is also something to keep in mind.

Here is my bruteforce solution (written in nim)

import osproc, os, random, strutils
proc gzipSize(text:string): int = 
    writeFile("tmp.css", text)
    discard execProcess("brotli.exe --in tmp.css --out tmp.css.gz --force")
    #discard execProcess("zopfli.exe tmp.css")
    #discard execProcess("pigz -9 --11 -f -k -n -T tmp.css")
    return getFileSize("tmp.css.gz").int
proc all(list: seq[string]): string =
    var temp = ""
    for item in list: temp &= item
    return temp
proc join(list: seq[string]): string =
    var temp = ""
    for item in list: temp &= ";"&item
    return temp
    
var raw = readFile("lit.css")
var count = 0
var parsed: seq[string] = @[]
var temp = ""
for ch in raw:
    temp &= ch
    if ch == '{': count += 1
    elif ch == '}':
        count -= 1
        if count == 0 and temp.len>0:
            parsed.add(temp)
            temp = ""
for i in 0..parsed.high-1:
    for j in i+1..parsed.high:
        var first = gzipSize(all(parsed))
        var cp = parsed
        cp[j] = parsed[i]
        cp[i] = parsed[j]
        var second = gzipSize(all(cp))
        if second < first: parsed = cp
echo gzipSize(all(parsed))

@davidmurdoch
Copy link
Author

I actually just wrote (with the help of some colleagues) a JS helper to iterate through every possible combination of selector and rule/declaration order, then zopfl()ied the resulting string (I'm ignoring specificity and the @media query for now). Unfortunately, at the rate it was running, it was going to take ~81 million years to complete. Haha. I let it run for about half an hour and it never completed even one iteration of a selector order (and I think there are ~2e+13 of them to run through!).

@ajusa
Copy link
Owner

ajusa commented Jan 17, 2018

Yeah, I noticed that when trying to write my own as well. I went with a shallow approach that would at least finish. I'll have to see if reordering the media query might help, my code ignores that as well. Thanks for exploring more into this!

@ajusa
Copy link
Owner

ajusa commented Jan 18, 2018

I swear I'll do this, just haven't had the time recently.

@ajusa
Copy link
Owner

ajusa commented Jan 25, 2018

Finally got around to getting this in, thanks!

@ajusa ajusa closed this as completed Jan 25, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants