Google's Webmaster Trends Analyst John Mueller recently termed a 2 seconds page load time as an "extremely high response time". The 2-second page load time benchmark is not new, but many websites still have an average page load time of 7 seconds. As a server management company, we are often asked how to make the page load time better. Today we'll see what can be done to improve the page speed of WordPress websites.
There are a lot of things that can be done at the site-admin level to improve the page load speed of WordPress sites. This includes optimizing images, disabling poorly performing plugins, enabling caching plugins, etc., but today we'll focus on what can be done at the server level to improve the site speed.
Note: I'm going to use the case of a single-server WordPress website for today's discussion. Multi-server installations with load balancers are an entirely different beast, which we'll cover on another occasion.
1. Add expires tag to static content
There's no reason why a returning visitor to your site should load all the images all over again. Adding expires tag to static content is a low hanging fruit. In Nginx servers, just add the below code to your configuration:
location ~* \.(css|js|gif|jpe?g|png|ico)$ { expires 30d; add_header Pragma public; add_header Cache-Control "public"; }
For those with Apache servers, I'd suggest you switch to Nginx servers as we'll discuss below.
2. Enable compression
Compressed files get downloaded faster. This is another low hanging fruit. Just put the below code in to your Nginx configuration. You'll save some bandwidth also along the way. :)
gzip on; gzip_proxied any; gzip_types text/plain text/xml text/css application/x-javascript; gzip_vary on; gzip_disable "MSIE [1-6]\.(?!.*SV1)";
3. Optimize the MySQL database
OK, now we are getting into a bit tougher territory. In a previous article we'd covered MySQL optimization quite in detail. If you'd like to start off right away, you can use a optimizer tool like mysqltuner.pl or tuning-primer.sh. It'll show you recommendations as shown in the screen shot. Just go ahead and make those changes in your my.cnf or if it is to optimize your tables, use the mysqlcheck command as shown below:
# mysqlcheck -o

4. Get Nginx and enable PHP-FPM
Being a life long fan of Apache myself, I know how difficult it sounds when an alternate web server is suggested, but performance comparisons show that Nginx is better able to handle large traffic volumes. Add to that FastCGI Process Manager for PHP, and you get a real solid foundation for a fast web server.
In an Ubuntu server, installation is as simple as executing these commands:
# apt-get install nginx-full
# apt-get install php5-fpm php5-mysql php5-gd
Now, edit your site configuration file (eg., /etc/nginx/sites-available/mysite) and add the below commands to get all your PHP files executed by PHP-FPM.
location ~ \.php$ { try_files $uri =404; #To use this setting put "cgi.fix_pathinfo = 0;" in php.ini fastcgi_split_path_info ^(.+\.php)(/.+)$; include fastcgi_params; fastcgi_index index.php; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; fastcgi_pass unix:/var/run/php5-fpm.sock; }
5. Install an OpCode cache
Ever seen those server load reports where PHP files are shown to consume CPU and memory? That's your WordPress files getting executed each time someone accesses your site. Each page in your site have many sections of PHP code which gets executed again and again. You can save server resources and execution time by caching an executed PHP code, so that next time it can just serve from memory.
APC and X-Cache are good OpCode caching programs. We'll see how we can configure APC cache. Install it by:
# apt-get install php5-apcu
Enable the APC module by:
php5enmod apcu
Now add the following settings to apc.ini (/etc/php5/mods-available/apc.ini)
[apc] extension=apc.so apc.enabled=1 apc.shm_size=48M apc.ttl=7200 apc.user_ttl=7200 apc.stat=0
And restart PHP-FPM
service php5-fpm restart
6. Enable Varnish
By now, you've transformed your web server into a lean, mean machine. Let's give it a boost with Varnish. Varnish will keep all the recurring resource requests (like images, files, etc.) in RAM so that your web server doesn't even need to be bothered if it isn't a NEW request.
Install Varnish with:
# apt-get install varnish libvarnish-dev
Now configure Nginx to listen to port 8080. Go to /etc/nginx/sites-enabled/mydomain.tld, and replace all instances of :80 with :8080, like below:
server {
listen [::]:8080 default_server;
server_name _;
return 444;
}
OK, so Nginx is waiting at 8080. Let's get Varnish to listen in at port 80 and pass on ONLY new requests to Nginx. Put this into /etc/default/varnish:
DAEMON_OPTS="-a :80 \ -T localhost:6082 \ -f /etc/varnish/default.vcl \ -S /etc/varnish/secret \ -s malloc,768m"
Now edit /etc/varnish/default.vcl and put these configuration entries in it:
backend default { .host = "127.0.0.1"; .port = "8080"; } sub vcl_recv { # Set the X-Forwarded-For header so the backend can see the original # IP address. If one is already set by an upstream proxy, we'll just re-use that. if (client.ip ~ upstream_proxy && req.http.X-Forwarded-For) { set req.http.X-Forwarded-For = req.http.X-Forwarded-For; } else { set req.http.X-Forwarded-For = regsub(client.ip, ":.*", ""); } ## Remove has_js and Google Analytics cookies. set req.http.Cookie = regsuball(req.http.Cookie, "(^|;\s*)(__[a-z]+|has_js)=[^;]*", ""); ## Remove a .;. prefix, if present. set req.http.Cookie = regsub(req.http.Cookie, "^;\s*", ""); ## Remove empty cookies. if (req.http.Cookie ~ "^\s*$") { unset req.http.Cookie; } # Site still uses some static files out of /files, cache them if (req.url ~ "^/files/site.*") { unset req.http.Cookie; } # enable caching of theme files if (req.url ~ "^/sites/www.site.*") { unset req.http.Cookie; } # Drupal js/css doesn.t need cookies, cache them if (req.url ~ "^/modules/.*\.(js|css)\?") { unset req.http.Cookie; } ## Pass cron jobs and server-status if (req.url ~ "cron.php") { return (pass); } if (req.url ~ ".*/server-status$") { return (pass); } } sub vcl_hash { if (req.http.Cookie) { hash_data(req.http.Cookie); } }
Restart Varnish, PHP and Nginx, and you are done!
Conclusion
The performance of your WordPress website depends a lot on your choice of plugins, themes and the way you use media in your website, but significant difference can be brought in if you handle the server environment just right. Today we've covered what can be done on a basic WordPress server system, but depending on the scale of your WordPress deployment, the methods of optimization will change. We'll cover more of that in our future articles.
In the mean time, check out our previous articles that covers how to secure your WordPress, and how to create a multi-site WordPress network.
Bobcares server administrators routinely help webmasters and service providers configure their infrastructure and keep their servers secure and responsive. Our server management services cover 24/7 monitoring, emergency administration, periodic security hardening, periodic performance tuning and server updates.
SEE HOW YOU CAN SETUP A RELIABLE SERVER INFRASTRUCTURE