|
#!/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 |
|
|