Mondi su mondi, sistemi di sistemi.

Git e l’ottimizzazione delle immagini

Si sa. Una delle cose da fare per otti­miz­zare le pre­sta­zioni di un sito è quella di sce­gliere accu­ra­ta­mente il for­mato delle imma­gini e ridurne il più pos­si­bile le dimen­sioni.1 Analogamente anche i css e java­script andreb­bero ridotti usando la minia­tu­riz­za­zione.2

Qual è il problema?

Queste otti­miz­za­zioni però pos­sono diven­tare un bell’intralcio se non auto­ma­tiz­ziamo tutti i passi neces­sari. Le imma­gini potrebbe essere otti­miz­zate prima dell’aggiunta al pro­getto ma spesso ven­gono pas­sate avanti e indie­tro prima di diven­tare defi­ni­tive; per non par­lare dei css o degli script, che pos­sono essere trat­tati solo all’ultimo momento prima del deploy­ment.3

Usiamo git

Ho pen­sato quindi di sfrut­tare git, aggan­ciando il post-processamento di que­sti file al momento dell’esportazione, quando viene creato il pac­chetto d’installazione.4

Per farlo dob­biamo modi­fi­care due file: config e info/attributes. Nel primo impo­stiamo i fil­tri:

     [filter "minify-css"]
         clean = cat
         smudge = java -jar /usr/local/bin/yuicompressor-2.4.2.jar --charset UTF8 --type css

     [filter "minify-js"]
         clean = cat
         smudge = java -jar /usr/local/bin/yuicompressor-2.4.2.jar --charset UTF8 --type js

     [filter "optimize-img"]
         clean = cat
         smudge = /Users/giorgio/bin/optimize-imgs

Nel secondo spe­ci­fi­chiamo i cri­teri di sele­zione dei file a cui appli­care que­sti fil­tri:

*.css filter=minify-css
 *.js filter=minify-js
 *.png filter=optimize-img
 *.gif filter=optimize-img
 *.jpg filter=optimize-img
 *.jpeg filter=optimize-img

Aggiriamo il pro­blema della pipeline

Il pro­blema prin­ci­pale è che git usa delle pipe­line5 per il pro­ces­sa­mento e non tutte le uti­li­ties usate per l’ottimizzazione sono pen­sate per essere impie­gate in que­sto modo, in par­ti­co­lare png­crush. La fun­zione di optimize-imgs è quindi quella di for­nire un minimo di uni­for­mità nell’utilizzo.

Lo script è incluso diret­ta­mente qui e pre­sup­pone di tro­vare nel PATH pngcrush, jpegtran e convert (ovvero, ImageMagick). Inoltre richiede tcl­lib, che è una dipen­denza di cui potrei fare a meno ma adesso non ho voglia di cam­biare lo script! ;-)

#! /usr/bin/env tclsh

package require cmdline

variable tmpFile /tmp/image

interp alias {} pngcrush {} exec pngcrush -rem alla -brute -reduce
interp alias {} jpegtran {} exec jpegtran
interp alias {} convert {} exec convert
interp alias {} cat {} exec cat
interp alias {} fileType {} exec file --brief --mime-type

proc createTempFile {} {
    variable tmpFile
    cat > $tmpFile
    switch [fileType /tmp/image] {
        {image/png} {
            set ext png
        }
        {image/gif} {
            set ext gif
        }
        {image/jpeg} {
            set ext jpg
        }
    }
    file rename -force $tmpFile $tmpFile.$ext
    return $tmpFile.$ext
}
proc optimize img {
    switch -glob -- $img {
        *.jpg -
        *.jpeg {
            set proc optimizeJPEG
        }
        *.png {
            set proc optimizePNG
        }
        *.gif {
            set proc optimizeGIF
        }
    }
    $proc $img /tmp/opt-image
}
proc optimizePNG {img dest} {
    pngcrush -rem alla -brute -reduce $img $dest > /dev/null
}

proc optimizeGIF {img dest} {
    convert -quiet $img $dest > /dev/null
}

proc optimizeJPEG {img dest} {
    set progressiveVariant [file dirname $dest]/prog-[file tail $dest]

    jpegtran -copy none -optimize -outfile $dest $img
    jpegtran -copy none -progressive -outfile $progressiveVariant $img

    if {[file size $dest] > [file size $progressiveVariant]} {
        file rename -force $progressiveVariant $dest
    } else {
        file delete $progressiveVariant
    }
}

proc main {args} {
    set args [::cmdline::getoptions args {
        f.arg {}
    } errore]
    dict with args {
        if {[string is false $f]} {
            set img [createTempFile]
            optimize $img
            cat /tmp/opt-image >@ stdout
        } else {
            optimize $f
            file rename -force /tmp/opt-image opt-[file tail $f]
        }

    }
}

main {*}$::argv

  1. Image opti­mi­za­tion. Sono quat­tro post che affron­tano in modo appro­fon­dito la que­stione.
  2. Come vedrete di seguito, uso YUI Compressor
  3. A meno che vi piac­cia leg­gere i file minia­tu­riz­zati!
  4. Git Attributes.
  5. Unix pipe­line: a set of pro­ces­ses chai­ned by their stan­dard streams, so that the out­put of each pro­cess (stdout) feeds direc­tly as input (stdin) to the next one.

Per proseguire

Commenti e trackback sono disabilitati.