Skip to content

Instantly share code, notes, and snippets.

@magnetikonline
Last active July 1, 2022 04:47
Show Gist options
  • Star 12 You must be signed in to star a gist
  • Fork 4 You must be signed in to fork a gist
  • Save magnetikonline/5087766 to your computer and use it in GitHub Desktop.
Save magnetikonline/5087766 to your computer and use it in GitHub Desktop.
Recursively pre-compress (gzip) CSS/JavaScript/webfont assets for use Nginx and its HttpGzipStaticModule module.
#!/bin/bash -e
function compressResource {
gzip --best --stdout "$1" >"$1.gz"
touch --no-create --reference="$1" "$1.gz"
echo "Compressed: $1 > $1.gz"
}
function main {
# fetch list of websites
local IFS=$'\n'
local appDir
for appDir in $(find /srv/http/* -maxdepth 0)
do
# fetch all existing gzipped CSS/JavaScript/webfont files and remove files that do not have a base uncompressed file
local compressFile
for compressFile in $(find "$appDir" -type f \( -name "*.css.gz" -or -name "*.js.gz" -or -name "*.eot.gz" -or -name "*.svg.gz" -or -name "*.ttf.gz" \))
do
if [[ ! -f ${compressFile%.gz} ]]; then
# remove orphan gzipped file
rm "$compressFile"
echo "Removed: $compressFile"
fi
done
# fetch all source CSS/JS/webfont files - excluding *.src.* variants (pre-minified CSS/JavaScript)
# gzip each file and give timestamp identical to that of the uncompressed source file
local sourceFile
for sourceFile in $(find "$appDir" -type f \( -name "*.css" -or -name "*.js" -or -name "*.eot" -or -name "*.svg" -or -name "*.ttf" \) \( ! -name "*.src.css" -and ! -name "*.src.js" \))
do
if [[ -f "$sourceFile.gz" ]]; then
# only re-gzip if source file is different in timestamp to existing gzipped version
if [[ ($sourceFile -nt "$sourceFile.gz") || ($sourceFile -ot "$sourceFile.gz") ]]; then
compressResource "$sourceFile"
fi
else
compressResource "$sourceFile"
fi
done
done
}
main
@mortenlarsen
Copy link

You can avoid the call to sed, as bash can remove the extension like below.:
$ a=test.css.gz
$ echo ${a%.gz}
test.css

@mortenlarsen
Copy link

You can also avoid the call to stat:
if [ ${file1} -ot ${file2} -o ${file1} -nt ${file2} ]; then
echo "mtime is different..."
fi

See: "man test"

@magnetikonline
Copy link
Author

Thanks for the feedback. Will add those changes - both very vaild & will avoid some slow exec calls.

EDIT: have now updated to use Bash string manipulations/file modification check in-builts.

@rabin-io
Copy link

Instead for-looping the output of find, you can use find -print0 and read -d '' to read the the output, this will work well with files with space's in them.

e.g: find "$appDir" -type f -regextype posix-extended -iregex ".*\.(${ext})\.gz$" -print0 | while read -d '' compressFile

I have taken your version and changed it a bit, https://gist.github.com/rabin-io/63000f48d1f9170f17ea5f73bcf84d66

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment