PageSpeed – WordPress themes in comparison

Your WordPress site is badly ranked on Google, even though you have invested a lot of time and money in high quality content and marketing? Your WordPress theme may prevent a better ranking.

We have compared top WordPress themes in terms of PageSpeed and PageLoad – the results can be found here. The three most popular themes compete against our SV100 WordPress theme in four different scenarios.

Here you can see how the chosen theme alone can have on the pageload – one of the many criteria for the Google ranking.

Avada

Avada is the most popular paid theme on ThemeForest.

OceanWP

OceanWP is the most popular theme in the official WordPress theme repository, which has been developed independently.

Twenty Nineteen

The Twenty Nineteen Theme is shipped together with WordPress and is the most up-to-date at the time of evaluation.

SV100

SV100 is our home theme and available free of charge.

Pagesize

The load time of your website depends heavily on the amount of data that is being transferred. Your visitors need more bandwidth or more patience to view your website. A theme should use resources as sparingly as possible, so that you have more freedom in your content.

Google recommends that a website should not have more than 1,600 kilobytes of PageSize.

Avada requires – without optimization – but already more than 1,700 kilobytes – without content. Therefore, it is better to choose a theme that is more economical with resources.

Below you can see the tested themes – the bigger the PageSize, the worse:

Space for your content

If you follow Google’s recommended PageSize budget – how much space do the WordPress themes give you? We compare here in the optimized scenario, i.e. with activated NGINX + WP-Rocket.

Pageload

The PageSize has a direct impact on the PageLoad – but this mainly affects the way from the server to the client. After that, the pages still have to be displayed in the browser. The loading of data and the structure of the pages happens a bit in parallel and can be influenced by the theme developer. Important data should be transferred first, unimportant later.

For our measurement we used the load time of pingdom – but in the PageSpeed tests you will find a more detailed breakdown – e.g. when the first content was drawn or from when the user can interact with the page.

Requests

The number of requests should be kept as low as possible – each request generates additional load. The more files the theme includes, such as media, styles, or scripts, the more requests the client and server need to process.

Intelligent and tidy asset loading through the theme effectively reduces the number of requests required and increases PageSpeed.

PageSpeed

The PageSpeed is a metric that expresses the speed of a website – it asks for numerous criteria that can be met. The maximum achievable value is 100/100.

The first value represents mobile speed, the second represents desktop devices. Since Google has switched indexing to Mobile-First, the first value for mobile devices is decisive for the ranking in the Google index.

Google is constantly increasing the requirements – new technologies are created and at some point assumed. Therefore, don’t wait for optimization – it doesn’t get any better.

Avada

Test-SitesPageSpeedPingdomPagesizePageloadRequests
Vanilla23/86871.743 KB681ms15
WP-Rocket26/90931.737 KB396 ms11
NGINX Optimized77/9894571 KB770 ms15
WP-Rocket + NGINX Optimized74/9997569 KB363 ms11

Ocean WP

Test-SitesPageSpeedPingdomPagesizePageloadRequests
Vanilla57/9484645 KB835 ms20
WP-Rocket90/10096636 KB271 ms7
NGINX Optimized84/9390285 KB672 ms20
WP-Rocket + NGINX Optimized100/10098265 KB318 ms7

Twenty Nineteen

Test-SitesPageSpeedPingdomPagesizePageloadRequests
Vanilla93/9984264 KB384 ms8
WP-Rocket100/10096222 KB181 ms5
NGINX Optimized100/1009556 KB275 ms8
WP-Rocket + NGINX Optimized100/1009847 KB141 ms5

SV100

Test-SitesPageSpeedPingdomPagesizePageloadRequests
Vanilla100/1009738 KB235 ms3
WP-Rocket100/1009815 KB173 ms4
NGINX Optimized100/100998 KB288 ms3
WP-Rocket + NGINX Optimized100/1009911 KB104 ms4

Recommendation

If usability, SEO or the Adwords Quality Score are important to your website – choose a WordPress theme that supports you and doesn’t slow you down.

Of course, the final values of your website also depend on the installed plugins, content and media – but here you can control more than the behavior of your theme. The theme forms the basis for the issue of your website. Look for actual modular themes that only deliver what is actually needed.

Configuration

We have set up our own instance for this test in our server cloud. At the time of the test we set up Plesk with Apache+NGINX and PHP 7.3.2. NGINX is especially useful for delivering static files – Apache, on the other hand, takes care of PHP script execution.

In addition, we have set up four test installations for each theme, each with different configurations – so we can compare how dependent a theme is on these optimizations – and where further optimization from the user’s point of view can be made for the respective Theme is no longer worthwhile.

Vanilla

We haven’t optimized anything else – only the theme has been installed.

WP-Rocket

The larger your website is, the more important it is to use a caching plugin. We worked for years with various caching plugins, which were however complicated to configure and regularly worked incorrectly – until the plugin WP-Rocket was released. We use this plugin in all our projects and are enthusiastic about the ease of use, stability and outstanding support.

NGINX Optimized

In Plesk it is possible to set additional NGINX directives with the primary admin account. If your web host uses Plesk and does not have access to this form, you should ask your web hoster to set the cache settings accordingly – as this is also possible at the domain level, your web hoster should be able to implement this quickly.

Plesk NGINX Directives
Plesk NGINX Directives

The following NGINX configuration enables compression for static files and increases the browser cache statement to the maximum – ideal for static files. Because WordPress includes files with version numbers in the URL, your website visitors always get up-to-date file versions despite the high cache duration.

# 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

Combine WP-Rocket with optimized NGINX directives, usually achieve the best result. We use a slightly customized version of the NGINX configuration of Maxime Jobin, which is specially optimized for use together 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 ~* \.(ico|gif|jpe?g|png|eot|otf|woff|woff2|ttf|ogg|webp)$ {
	etag on;
	expires max;
}