PageSpeed – WordPress Themes Comparison

This analysis compares the pagespeed performance of different WordPress-Themes

In the following summaries, you will find links to the test installations as well as the PageSpeed from time of measurement. Please note, that results can vary from time to time – we take the most stable value from multiple tests. This text is focused on the technical aspect – if you need consultance on how this affects your website, just contact us.

General Configuration for the Pagespeed Comparsion

We have used a dedicated instance on our Servercloud for this test. During the test, there is a Apache+NGINX, PHP 7.4.2 configured in Plesk. NGINX is good to deliver static files – Apache takes care for running PHP-scripts.

Additionally we have set up four different configured installations for each theme, so that we are able to compare how a theme depends on an optimized infrastructure – and where optimizing would bring the most effect from user’s point of view.

The maximum score is 100/100. The first value is the mobile performance score and the second one is for desktop-clients. As Google switches to mobile-first indexing, this is an important information.

Configurations in Detail

Vanilla

We have optimized nothing – just the theme was installed.

WP-Rocket

The bigger the website, the more important is using a caching plugin. We have worked with different caching plugins over years, which were not easy to set up and had unsolved issues – until the plugin WP-Rocket was released. We use this plugin for our projects and are excited about the user friendly interface, stability and outstanding support.

NGINX Optimized

We have set up additional NGINX-Directives in Plesk. If your webhoster uses Plesk and you have no access to this form, you should ask your webhoster to set the caching settings for you. As this is even possible on domain level, your webhoster should do that easily for you.

Plesk NGINX Direktiven
Plesk NGINX Direktiven

The following NGINX-Configuration is for maximized browser caching of static files. As WordPress attaches assets like JavaScript or CSS with version numbers in the URL, your users will always get the latest version.

# BROWSER CACHE
gzip on;
gzip_min_length  1100;
gzip_buffers  4 32k;
gzip_types    text/plain application/javascript application/x-javascript text/xml text/css image/svg+xml;

location ~* \.(css|js|svg)$ {
	gzip_vary on;
	expires max;
}

location ~* \.(ico|gif|jpe?g|png|eot|otf|woff|woff2|ttf|ogg)$ {
	expires max;
}

WP-Rocket + NGINX

If you combine WP-Rocket with optimized NGINX-Directives, you should gain the best results. We use a slightly adjusted version of the NGINX configuration of Maxime Jobin, which is especially optimized for use with WP-Rocket.

###################################################################################################
# Rocket-Nginx
#
# Rocket-Nginx is a NGINX configuration to speedup your WordPress
# website with the cache plugin WP-Rocket (http://wp-rocket.me)
#
# Author: Maxime Jobin
# URL: https://github.com/maximejobin/rocket-nginx
#
# Tested with WP-Rocket version: 3.0.5.1
# Tested with NGINX: 1.15 (mainline)
#
# Version 2.1.1
#
###################################################################################################

# Add debug information into header
set $rocket_debug 0;

###################################################################################################
# Do not alter theses values
#
set $rocket_bypass 1;				# Should NGINX bypass WordPress and call cache file directly ?
set $rocket_encryption "";			# Is GZIP accepted by client ?
set $rocket_file "";				# Filename to use
set $rocket_is_bypassed "No";		# Header text added to check if the bypass worked or not. Header: X-Rocket-Nginx-Serving-Static
set $rocket_reason "";				# Reason why cache file was not used. If cache file is used, what file was used
set $rocket_https_prefix "";		# HTTPS prefix to use when cached files are using HTTPS
set $rocket_hsts 0;					# Is HSTS is off (0) by default. Will be turned on (1) if request is HTTPS

# HSTS value
set $rocket_hsts_value "max-age=31536000; includeSubDomains";

###################################################################################################
# PAGE CACHE
#

# Is GZIP accepted by client ?
if ($http_accept_encoding ~ gzip) {
	set $rocket_encryption "_gzip";
}

# Is Brotli accepted by client ?
if ($http_accept_encoding ~ br) {
	set $rocket_encryption "";
}

# Is SSL request ?
if ($https = "on") {
	set $rocket_https_prefix "-https";
	set $rocket_hsts 1;
}

# If HSTS is disabled, unset HSTS set for Rocket-Nginx configuration
if ($rocket_hsts = "0") {
	set $rocket_hsts_value "";
}

# File/URL to return IF we must bypass WordPress
# Desktop: index.html or index-https.html
# Mobile:  index-mobile.html or index-mobile-https.html
set $rocket_end "/cache/wp-rocket/$http_host/$request_uri/index$rocket_https_prefix.html$rocket_encryption";
set $rocket_url "/wp-content$rocket_end";
set $rocket_file "$document_root/wp-content$rocket_end";
set $rocket_mobile_detection "$document_root/wp-content/cache/wp-rocket/$http_host/$request_uri/.mobile-active";

# Do not bypass if it's a POST request
if ($request_method = POST) {
	set $rocket_bypass 0;
	set $rocket_reason "POST request";
}

# Do not bypass if arguments are found (e.g. ?page=2)
if ($is_args) {
	set $rocket_bypass 0;
	set $rocket_reason "Arguments found";
}

# Do not bypass if the site is in maintenance mode
if (-f "$document_root/.maintenance") {
	set $rocket_bypass 0;
	set $rocket_reason "Maintenance mode";
}

# Do not bypass if one of those cookie if found
# wordpress_logged_in_[hash] : When a user is logged in, this cookie is created (we'd rather let WP-Rocket handle that)
# wp-postpass_[hash] : When a protected post requires a password, this cookie is created.
if ($http_cookie ~* "(wordpress_logged_in_|wp\-postpass_|woocommerce_items_in_cart|woocommerce_cart_hash|wptouch_switch_toogle|comment_author_|comment_author_email_)") {
	set $rocket_bypass 0;
	set $rocket_reason "Cookie";
}

if (-f "$rocket_mobile_detection") {
	set $rocket_bypass 0;
	set $rocket_reason "Specific mobile cache activated";
}

# Do not bypass if the cached file does not exist
if (!-f "$rocket_file") {
	set $rocket_bypass 0;
	set $rocket_reason "File not cached";
}

# If the bypass token is still on, let's bypass WordPress with the cached URL
if ($rocket_bypass = 1) {
	set $rocket_is_bypassed "Yes";
	set $rocket_reason "$rocket_url";
}

# Clear variables if debug is not needed
if ($rocket_debug = 0) {
	set $rocket_reason "";
	set $rocket_file "";
}

# If the bypass token is still on, rewrite according to the file linked to the request
if ($rocket_bypass = 1) {
	rewrite .* "$rocket_url" last;
}

# Add header to HTML cached files
location ~ /wp-content/cache/wp-rocket/.*html$ {
	etag on;
	add_header Vary "Accept-Encoding, Cookie";
	add_header Cache-Control "no-cache, no-store, must-revalidate";
	add_header X-Rocket-Nginx-Serving-Static $rocket_is_bypassed;
	add_header X-Rocket-Nginx-Reason $rocket_reason;
	add_header X-Rocket-Nginx-File $rocket_file;
	add_header Strict-Transport-Security "$rocket_hsts_value";

}

# Do not gzip cached files that are already gzipped
location ~ /wp-content/cache/wp-rocket/.*_gzip$ {
	etag on;
	gzip off;
	types {}
	default_type text/html;
	add_header Content-Encoding gzip;
	add_header Vary "Accept-Encoding, Cookie";
	add_header Cache-Control "no-cache, no-store, must-revalidate";
	add_header X-Rocket-Nginx-Serving-Static $rocket_is_bypassed;
	add_header X-Rocket-Nginx-Reason $rocket_reason;
	add_header X-Rocket-Nginx-File $rocket_file;
	add_header Strict-Transport-Security "$rocket_hsts_value";

}

# Debug header (when file is not cached)
add_header X-Rocket-Nginx-Serving-Static $rocket_is_bypassed;
add_header X-Rocket-Nginx-Reason $rocket_reason;
add_header X-Rocket-Nginx-File $rocket_file;

# No HSTS header added here. We suppose it's correctly added in the site configuration

###################################################################################################

# BROWSER CACHE
gzip on;
gzip_min_length  1100;
gzip_buffers  4 32k;
gzip_types    text/plain application/javascript application/x-javascript text/xml text/css image/svg+xml;

location ~* \.(css|js|svg)$ {
	etag on;
	gzip_vary on;
	expires max;
}

location ~* \.(ico|gif|jpe?g|png|eot|otf|woff|woff2|ttf|ogg)$ {
	etag on;
	expires max;
}

Twenty Nineteen

The Twenty Nineteen theme is delivered together with WordPress and is the most recent version during the test.

Theme Installation & Configuration

Test-SitesPageSpeedPageload
Vanilla93/99264 KB
WP-Rocket100/100222 KB
NGINX Optimized99/10056 KB
WP-Rocket + NGINX Optimized100/10047 KB

Ocean WP

Ocean WP is the most popular theme in the official WordPress-Theme-Repository that’s not independently developed.

Theme Installation & Configuration

Test-SitesPageSpeedPageload
Vanilla63/93645 KB
WP-Rocket92/100 636 KB
NGINX Optimized87/96270 KB
WP-Rocket + NGINX Optimized98/100265 KB

Avada

Avada is the most popular paid theme on ThemeForest.

Theme Installation & Configuration

Test-SitesPageSpeedPageload
Vanilla22/871.743 KB
WP-Rocket26/901.737 KB
NGINX Optimized81/92571 KB
WP-Rocket + NGINX Optimized84/100569 KB

SV 100

SV 100 is our own WordPress theme and will be available for free.

Theme Installation & Configuration

Test-SitesPageSpeedPageload
Vanilla100/10038 KB
WP-Rocket100/10015 KB
NGINX Optimized100/1008 KB
WP-Rocket + NGINX Optimized100/10012 KB

Conclusion

If user-friendliness, SEO or Adwords-Quality-Score is important for you – you should decide for a WordPress theme that brings a good score here. Of course, you may be able to decrease the score by adding plugins or have unoptimized media or content – but that’s up to you. You may not want to relinquish a critical feature, but a lightweight WordPress theme gives you extra freedom.

Search for real modular themes which only serve you what’s actually needed and enables you to disable features without keep loading their assets. Plus, if something goes wrong, it’s much easier to debug.

For our SV 100 WordPress theme, unfortunately, we are not able to gain more than 100/100 – but that’s why we will extend this test to e.g. Pingdom in the future – just to go the extra mile for you.