This blog is currently built using Jekyll, a static site generator written in ruby. It’s only a part of the stack, which also involves various build scripts and optimization tools I use to (as of this writing) score a 100 on pagespeed insights

Build Scripts

I’ve summarized them in this post, but here are the full build scripts:

Optimizations

  • HTML Minification - remove whitespace / unnecessary comments
  • CSS Minification - minify all css to remove whitespace / comments
  • CSS Inlining - since the css size is small I inline the /css/rich_v2.css file into the <head> section to save a request.
  • Fonts - all fonts are hosted locally instead of using google fonts
  • Image Optimization - optimize all png, jpg images
  • Compression - Compress automatically using CloudFront

How it works - build.sh

1. Jekyll - static site generator

bundle exec jekyll build

2. Gulp - This is used for css/html minification

Inside here, gulp-clean-css, gulp-htmlmin, gulp-inline-source are used for minification and optimizations (with more or less default parameters)

# Minify artifacts
gulp minify-html minify-css

3. imagemagick (aka “convert”) - used for image conversions

# Convert profile image into a PNG
convert _site/img/profile_image.jpg _site/img/profile_image.png

4. png2ico - used to generate .ico files

# Convert profile image into an ICO file
png2ico _site/favicon.ico _site/img/profile_image.png

5. exiftool - used for stripping exif metadata

# Strip All EXIF DATA (except orientation)
find _site -type f \( -name "*.jpg" -o -name "*.JPG" -o -name "*.jpeg" -o -name "*.png" \) -print0 | while read -d $'\0' f; do
  exiftool -overwrite_original -all= -tagsfromfile @ -Orientation "$f"
done

6. optipng - used to optimize png images

# Optimize PNG files
find _site -type f \( -name "*.png" \) -print0 | while read -d $'\0' f; do
  optipng "$f"
done

7. jpegoptim - used to optimize jpeg images

# Optimize JPG
find _site -type f \( -name "*.jpg" -o -name "*.JPG" -o -name "*.jpeg" \) -print0 | while read -d $'\0' f; do
  jpegoptim --size=200k "$f"
done

How it works - upload.sh

1. Set up s3 website

First, we set the s3 website’s index / and error documents

# Setup the website
aws s3 website "s3://$S3_BUCKET" \
  --profile "$AWS_PROFILE" \
  --index-document "$INDEX_DOCUMENT" \
  --error-document "$ERROR_DOCUMENT" &&

2. Upload entire site

Next, we upload to the s3 bucket, with the public read flag set. The --delete flag ensures that stale files that have been renamed or deleted are removed.

# Upload
aws s3 sync \
  --profile "$AWS_PROFILE" \
  --acl public-read \
  --sse \
  --delete \
  _site "s3://$S3_BUCKET" &&

3. Set up cache-control

# Add cache-control headers for poster images
# This instructs s3/cloudfront to send Cache-Control headers.
aws s3 cp \
  "s3://$S3_BUCKET/img/headers/" \
  "s3://$S3_BUCKET/img/headers/" \
  --profile "$AWS_PROFILE" \
  --metadata-directive REPLACE \
  --recursive \
  --cache-control max-age=31536000

4. Invalidate Edge Caches

# Invalidate Edge Caches
aws cloudfront create-invalidation \
  --profile "$AWS_PROFILE" \
  --distribution-id "$DISTRIBUTION_ID" \
  --paths /\*