Skip to content

Instantly share code, notes, and snippets.

@westonruter
Last active October 12, 2025 05:40
Show Gist options
  • Save westonruter/27ec41372df93248f6237cf99c2da30c to your computer and use it in GitHub Desktop.
Save westonruter/27ec41372df93248f6237cf99c2da30c to your computer and use it in GitHub Desktop.
WordPress Theme Performance Benchmarking Script
#!/bin/bash
# =============================================================================
#
# WordPress Theme Performance Benchmarking Script
#
# This script automates the process of benchmarking the performance impact of a
# change across multiple WordPress themes. It activates each theme, runs
# Lighthouse multiple times for a "before" and "after" URL, calculates the
# median performance score, and outputs the results in a Markdown table.
#
# Author: Gemini
# Date: 2025-10-11
#
# Prerequisites:
# 1. Lighthouse CLI: `npm install -g lighthouse`
# 2. jq (JSON processor): `brew install jq`
# 3. bc (arbitrary-precision calculator): `brew install bc` (usually pre-installed)
# 4. A running `wordpress-develop` environment.
#
# Usage:
# 1. Save this file as `benchmark.sh`.
# 2. Make it executable: `chmod +x benchmark.sh`.
# 3. Run it from your terminal, passing the two URLs to compare:
# ./benchmark.sh "http://localhost:8000/before-url" "http://localhost:8000/after-url"
#
# =============================================================================
# --- Configuration ---
# Path to your local wordpress-develop repository.
# The user-provided path is used as the default.
WP_DEVELOP_PATH="$HOME/repos/wordpress-develop"
# Number of Lighthouse runs for each URL to calculate the median from.
NUM_RUNS=5
# Array of theme slugs to test.
THEMES=(
"twentyten"
"twentyeleven"
"twentytwelve"
"twentythirteen"
"twentyfourteen"
"twentyfifteen"
"twentysixteen"
"twentyseventeen"
"twentynineteen"
"twentytwenty"
"twentytwentyone"
)
# --- Argument Parsing ---
if [ "$#" -ne 2 ]; then
echo "Usage: $0 <url_before> <url_after>" >&2
echo "Error: Please provide exactly two URLs as arguments." >&2
exit 1
fi
URL_A=$1
URL_B=$2
# --- Pre-flight Checks ---
# Check if jq is installed.
if ! command -v jq &> /dev/null; then
echo "Error: 'jq' is not installed. It is required to parse Lighthouse JSON output." >&2
echo "Please install it. On macOS with Homebrew, run: brew install jq" >&2
exit 1
fi
# Check if bc is installed.
if ! command -v bc &> /dev/null; then
echo "Error: 'bc' is not installed. It is required for calculations." >&2
echo "Please install it. On macOS with Homebrew, run: brew install bc" >&2
exit 1
fi
# Check if the WordPress development directory exists.
if [ ! -d "$WP_DEVELOP_PATH" ]; then
echo "Error: WordPress develop directory not found at '$WP_DEVELOP_PATH'." >&2
echo "Please update the WP_DEVELOP_PATH variable in this script." >&2
exit 1
fi
# --- Main Script ---
# Function to run Lighthouse and extract the performance score.
# Arguments:
# $1: The URL to test.
# Returns:
# The performance score (0-100).
run_lighthouse() {
local url=$1
# Run Lighthouse, suppress verbose logging, output JSON, and run headless.
# Use jq to parse the JSON and get the performance score.
# The score is a value from 0 to 1; multiply by 100 and round to get an integer.
local score=$(lighthouse "$url" --output=json --only-categories=performance --chrome-flags="--headless" 2>/dev/null | jq '.categories.performance.score * 100 | round')
echo "$score"
}
# Function to calculate the median from a list of scores.
# Assumes an odd number of runs.
# Arguments:
# $@: An array of scores.
# Returns:
# The median score.
calculate_median() {
local scores=("$@")
# Sort the scores numerically.
local sorted_scores=($(printf '%s\n' "${scores[@]}" | sort -n))
# The median is the middle element.
local median_index=$(( (NUM_RUNS - 1) / 2 ))
echo "${sorted_scores[$median_index]}"
}
# --- Execution ---
echo "Starting WordPress performance benchmark..." >&2
echo "URL A (Before): $URL_A" >&2
echo "URL B (After): $URL_B" >&2
echo "Number of themes to test: ${#THEMES[@]}" >&2
echo "Lighthouse runs per URL: $NUM_RUNS" >&2
echo "--------------------------------------------------" >&2
echo "" >&2
# Print the Markdown table header.
echo "| Theme | Before Score (Median) | After Score (Median) | Relative Diff | Percentage Diff |"
echo "|:----------------------|----------------------:|---------------------:|--------------:|----------------:|";
# Loop through each theme.
for theme in "${THEMES[@]}"; do
echo -e "\nProcessing theme: $theme..." >&2
# Activate the theme using the provided npm script.
echo " > Activating theme..." >&2
npm --prefix "$WP_DEVELOP_PATH" run env:cli -- theme activate "$theme" > /dev/null 2>&1
if [ $? -ne 0 ]; then
echo " ! Failed to activate theme '$theme'. Skipping." >&2
continue
fi
# Array to hold scores for URL A ("Before").
scores_a=()
echo " > Running Lighthouse for 'Before' URL (A)..." >&2
for (( i=1; i<=NUM_RUNS; i++ )); do
echo " - Run $i of $NUM_RUNS..." >&2
score=$(run_lighthouse "$URL_A")
if [[ -n "$score" ]]; then
scores_a+=("$score")
else
echo " ! Warning: Failed to get score for run $i on URL A." >&2
fi
done
# Array to hold scores for URL B ("After").
scores_b=()
echo " > Running Lighthouse for 'After' URL (B)..." >&2
for (( i=1; i<=NUM_RUNS; i++ )); do
echo " - Run $i of $NUM_RUNS..." >&2
score=$(run_lighthouse "$URL_B")
if [[ -n "$score" ]]; then
scores_b+=("$score")
else
echo " ! Warning: Failed to get score for run $i on URL B." >&2
fi
done
# Calculate the median scores and differences if we have enough data.
if [ "${#scores_a[@]}" -gt 0 ] && [ "${#scores_b[@]}" -gt 0 ]; then
median_a=$(calculate_median "${scores_a[@]}")
median_b=$(calculate_median "${scores_b[@]}")
relative_diff=$((median_b - median_a))
# Add '+' prefix to positive relative difference.
if [ "$relative_diff" -gt 0 ]; then
relative_diff="+$relative_diff"
fi
if [ "$median_a" -eq 0 ]; then
percentage_diff="N/A"
else
# Use bc for floating-point arithmetic.
percentage_diff=$(echo "scale=1; ($median_b - $median_a) * 100 / $median_a" | bc)
# Check if the result is positive and add a '+' prefix if so.
if (( $(echo "$percentage_diff > 0" | bc -l) )); then
percentage_diff="+$percentage_diff"
fi
percentage_diff="${percentage_diff}%"
fi
# Print the Markdown table row.
printf "| %-21s | %21s | %20s | %13s | %15s |\n" "$theme" "$median_a" "$median_b" "$relative_diff" "$percentage_diff"
else
printf "| %-21s | %21s | %20s | %13s | %15s |\n" "$theme" "ERROR" "ERROR" "ERROR" "ERROR"
fi
done
echo "" >&2
echo "--------------------------------------------------" >&2
echo "Benchmark complete." >&2
bash benchmark.sh "http://localhost:8000/sample-page/?enable_plugins=none&script_debug=0" "http://localhost:8000/sample-page/?enable_plugins=always-load-block-styles-on-demand&script_debug=0" 
Theme Before Score (Median) After Score (Median) Relative Diff Percentage Diff
twentyten 97 100 +3 +3.0%
twentyeleven 95 99 +4 +4.2%
twentytwelve 87 95 +8 +9.1%
twentythirteen 77 85 +8 +10.3%
twentyfourteen 78 87 +9 +11.5%
twentyfifteen 77 85 +8 +10.3%
twentysixteen 80 88 +8 +10.0%
twentyseventeen 81 86 +5 +6.1%
twentynineteen 89 96 +7 +7.8%
twentytwenty 81 87 +6 +7.4%
twentytwentyone 91 96 +5 +5.4%
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment