7374756666

Optimizing images for Google PageSpeed Insights

Google Page Speed Insights often advises to optimize images to reduce the page size, this is often easier said than done especially for sites that allow user uploads such as Wordpress.

The following script will optimize images once per image.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
#!/bin/bash
PATH_TO_OPTIMIZE="/var/www/html"
cd "$PATH_TO_OPTIMIZE"
echo "Optimizing $PATH_TO_OPTIMIZE"
# find jpeg images which have been modified since the last optimization
find . -path "./optimized" -prune -o -newer "$PATH_TO_OPTIMIZE/.opt" -name "*.png" -print > /tmp/optpng
# find png images which have been modified since the last optimization
find . -path "./optimized" -prune -o -newer "$PATH_TO_OPTIMIZE/.opt" -name "*.jpg" -print > /tmp/optjpeg
# update last optimization time, yes there is a race condition where a file could be uploaded
# while files are being found, I'll fix this one day
touch "$PATH_TO_OPTIMIZE/.opt"
# optimize pngs
total=$(wc -l /tmp/optpng)
i=0
while read f
do
    ((i++))
    echo "$i of $total"
    file=$(basename $f)
    dir=$(dirname $f)
    mkdir -p optimized/$dir
    /usr/local/bin/pngquant -v --force --speed 1 --quality=50-100 --output optimized/$dir/$file $f 
    optipng -o7 -clobber -out optimized/$dir/$file optimized/$dir/$file
done < /tmp/optpng
total=$(wc -l /tmp/optjpeg)
i=0
while read f
do
    ((i++))
        echo "$i of $total"
    file=$(basename $f)
    dir=$(dirname $f)
    mkdir -p optimized/$dir
    convert -verbose -strip -sampling-factor 4:2:0 -colorspace RGB -interlace LINE -quality 80 $f optimized/$dir/$file
done < /tmp/optjpeg
rm /tmp/optjpeg
rm /tmp/optpng

You can set up a cron job like this to optimize images, note the flock is important to stop multiple runs at the same time

*/15 * * * * www-data /usr/bin/flock -x -w 60 /tmp/wpperform-optimizeimages.lock /usr/local/bin/wpperform-optimizeimages > /dev/null

The above script doesn't overwrite the original files it stores them in a subfolder called optimized, you can use some websever rewrite rule wizardry to show them instead of the originals. Nginx's try_files is an option.

On the intial optimization you'll want to run

touch -t  [[CC]YY]MMDDhhmm $PATH_TO_OPTIMIZE/.opt

Where the date is older than the oldest file you want to optimize