I floated the idea of these articles to enthusiastic approval on /r/wordpress/, so here we are. My name is Mark, and I’m a jack of all trades: I write, code, design and admin for a living. Sometimes the write, code, design, and admin has a happy intersection with WordPress.

The site precedes the recent backlash against heavy sites (“The Verge’s web sucks”), but it stems from the same sentiment. I built this site’s theme, Sheepie, from scratch with the one goal of “make it faster.” I did this because I’ve seen any number of awful WordPress sites that chug under 15 JS libraries and 20 stylesheets. Fuck, half the questions on /r/wordpress/ boil down to “added plugin site broek hepl fix plzzzzz!”

My outlook is this: it’s great that WordPress has lowered the bar to build a website. WordPress’ plugins and themes are a set of interchangeable modules that you swap, mix and match to your heart’s desire. The problem with this model is that WordPress has lowered the bar to build a website. There is a whole class of website creators who can’t even write code. These people drag, drop, forget and panic when it break, because they can’t code.

Grr. These people raise my ire, but I have to respect the space they inhabit: it means WordPress is working. This is a blog for everyone, and they’re everyone.

The articles in this series will go up as my work permits. Today is Tuesday. I’ll try to get one per week every Tuesday. I’ll start with Sheepie and my site’s stack before I move onto a larger project that is almost complete. They share a bunch of code; I use Sheepie and this site as a testbed. Sheepie is simpler too, so I’ll start here.

Corrections and addendum are welcome. If you see something wrong, tell me. If you have something to add, say it!

Sheepie

https://github.com/bhalash/sheepie

Sheepie is available on GitHub. 97% of code in the repo is mine (normalize.css isn’t), and 100% of files are under permissive licenses. The PHP is GPLv3; the CSS and JS are MIT. I’m proud to open source my code in the face of shit like this. You’re all welcome to fork, share and use my code!

Building Sheepie

I use Node.js and gulp.js to provide several dependent packages for Sheepie. There are a few IE9 polyfills, and as well as that Gulp to transpile SCSS and minify JavaScript. There are no .css files or .min.js files, so you’ll need to install and build yourself. First run

npm install

from the root folder, then

gulp

There are two gulp watch tasks:

default transpiles “live” CSS without a sourcemap, and minifies JavaScript on save;

transpiles “live” CSS without a sourcemap, and minifies JavaScript on save; css-dev-watch transpiles SCSS with a sourcemap for debugging.

There is a switch in the JavaScript loader that selects unminified JavaScript if WP_DEBUG is true .

Development Environment

All hail the glorious vim master race. Here is my vimrc file. I work from a Macbook with an external display, and I remote into my Linux server, Linux has superior command line tools.

Ready?

WordPressish Beholding

There’s no one magic bullet to make your WordPress site faster, and in truth stock does a great job on small scales. Problems start in two way:

Server load. Your turn your site into a magazine. You build your audience up to to a few tens of thousands of visitors a day. Then you fail to account for the load of 45+ posts queried per page, tens to hundreds of times per second. WordPress has to query the database, fetch the images, render the page and serve the content. Any overhead adds up, fast. Client load. You want all the pretty effects. You want the parallax scrolling, the transitional slideshow, the animated swirling dingdong blingbling widgets. You wrap your content in glittery pointless shit that bogs down my browser. I mean, come on, I don’t need a fucking slideshow or a Google Maps widget to find your restaurant’s menu or opening hours. Learn how to write a landing page already.

Grumble.

There’s no single point of improvement in speed. You have to look at everything, think and work your way down in the manner of water falling.

First, I start on my server: my site runs on an SSD with breathtaking bandwidth. I tweak the .htaccess file and PageSpeed.

Second, I optimize WordPress: Tweak page load, remove or change plugins, and cache queries and pages.

Third, I look at what goes to the browser: remove JavaScript, reduce images served, compress content. I do a good deal, but I’ll be the first to admit I could do more.

Reduce, remove, resize, and reconsider should be your mantra.

0. Stop and think

Fucking really. How many of us sleep through guides? How many of us lift snippets from a page with nary a thought for “does this improve my site?” Go further and ask yourself: can I code it myself? How can I optimize this? Can I make this better? Be curious, be discontent: we don’t improve things whose state makes us happy.

1. Have a VPS

My WordPress runs on Ubuntu 14.04 LTS on a Linode VPS, because my housemate got me a great deal on price. I am not affiliated with Linode, so go use whatever VPS provider you like. I use apache2 over nginx because my clients all use apache. It pays more to keep up with what they used, since there isn’t any chance I can change their setup.

Shared hosts are awful:

Your website shares time and resources with dozens of other websites hosted on the same machine.

You will only have curtailed access to the system itself through FTP uploads and a limited control panel of some sorts.

They cost more than a VPS. I pay USD ~€8.70/month for my Linode VPS. I was on a shared Blacknight package before that which cost €15/month.

Virtual private servers are awful:

There is a terrible freedom; you now the freedom to do anything you want, but have to do it yourself.

Your server will Become a Target, and it is only on your head if you fail.

I assume: you have a VPS, you have WordPress, you have a good taste in whiskey, you want to make stuff faster.

2. .htaccess and caches

I started down the rabbit hole of performance in a boards.ie thread where I requested feedback on this site. Responders said much about performance: I continued to ghetto host my content out of Dropbox, and I had a VPS then. I didn’t do anything with Apache configuration. In other words I had lots of low-hanging fruit.

There are a hundred or more WordPress cache plugins. Some will just tweak .htaccess file rules. Others will save the rendered HTML of a page and serve that to visitors instead. A few will connect your site to a content distribution network. I haven’t tried enough of them to recommend one over another.

I discovered WP Super Cache, found it met my needs (remember what I said about that which make us happy?), and never looked at another. I use it in conjunction with a bunch of .htaccess rules I’ve picked up on the Internet. It’s a great plugin: I turned it on, picked some aggressive settings and never looked at it again.

Onto .htaccess . I serve my images from the Ix, while my blog lies on the main domain. There are a bunch of other subdomains named for Dune planets that run test sites or fun little projects. In reality, their files are in /var/www and usually one folder over from one another. I added these changes to my apache2.conf file, and included overrides at the foo.bhalash.com.conf level. I didn’t want to duplicate the default for each server over and again.

I, for example, disable PageSpeed and many cache rules for my sandbox. It’s more important for me to see updates and changes as I make them, than it is is for me to serve faster.

This gist holds my config. To break down the rules:

<ifmodule mod_mime.c> # Add minetypes for gzipping. AddType application/javascript js AddType application/vnd.ms-fontobject eot AddType application/x-font-ttf ttf ttc AddType font/opentype otf AddType application/x-font-woff woff AddType image/svg+xml svg svgz AddType video/mp4 mp4 AddType image/x-icon .ico AddEncoding x-gzip .svgz </ifmodule>

These mimetypes tell the server what type of file to associate with a given extension. This permits magic, but performs no magic itself. The Apache Software Foundation hosts a great introductory article, and the Internet has many great resources and questions on mimetypes.

Next comes some magic. These rules set up browser cache controls:

<filesmatch "\.(ico|svg|woff|eot|ttf)$"> Header set Cache-Control "max-age=31536000, public" </filesmatch> <filesmatch "\.(jpg|png|gif|css|js|mp4)$"> Header set Cache-Control "max-age=31536000, public" </filesmatch>

LimeCanvas have a thorough explanation. PageSpeed overrides this, because of how it rewrites website content. If you go to WebPagetest and see this warning

FAILED - (5.0 minutes)

well, there’s your culprit. The third piece of Apache magic is gzip:

<ifmodule mod_deflate.c> AddOutputFilterByType DEFLATE text/html text/plain text/css application/json AddOutputFilterByType DEFLATE application/javascript AddOutputFilterByType DEFLATE text/xml application/xml text/x-component AddOutputFilterByType DEFLATE image/svg+xml AddOutputFilterByType DEFLATE application/xhtml+xml application/rss+xml application/atom+xml AddOutputFilterByType DEFLATE image/x-icon image/svg+xml application/vnd.ms-fontobject application/x-font-ttf font/opentype AddOutputFilterByType DEFLATE video/mp4 </ifmodule>

The Apache Software Foundation document it here here. TL;DR: you pass off work to the browser. Instead of consuming bandwidth and transfer time for an asset, you send a gzipped (compressed) asset to the browser to unpack and process. More work for the browser, less work for the server.

3. PageSpeed

PageSpeed a module for Nginx and Apache authored by Google. A full account of what PageSpeed can do is beyond the scope of this article. I feel it’s good enough to say that it optimizes your server with the goal of reducing load time. You can download PageSpeed from Google here. The download page has installation instructions: install the .deb package; update apt ; a2enmod pagespeed ; and restart Apache.

Clear enough, right? You will find PageSpeed’s at /etc/apache2/mods-available/pagespeed.conf on Ubuntu.

Beyond enabling PageSpeed, the first filters I enabled inlines (CSS/JS) and minifies (CSS/JS) text assets:

ModPagespeedEnableFilters inline_css,inline_javascript ModPagespeedEnableFilters rewrite_javascript,rewrite_css ModPagespeedEnableFilters collapse_whitespace,elide_attributes

My hand is up here as I admit I don’t take full advantage of this. Browsers render the page as the CSS downloads, so the logical order of your CSS rules should reflect your HTML’s (mine does). Thing is, PageSpeed would like you to break your CSS into small snippets. The goal is that CSS for your above the fold content there with the content as the page loads. But you have to break up your CSS into small pieces for this; no more than a couple of KB at most. My CSS isn’t; it’s all in a single 24 KB minified file. The milliseconds I can gain in load time on my personal blog aren’t worth the hours of effort to refactor.

Next, I add each of my domains:

ModPagespeedDomain *.bhalash.com

PageSpeed has options to recompress JPG files on the fly as it serves them. I do not use this because I don’t use the WordPress media library. Instead I upload files to Ix using a script that encodes them with ImageMagick.

ModPagespeedImageRecompressionQuality 85

The last non-per-domain setting I apply is to map all URLs in Ix to a local filesystem path:

ModPagespeedLoadFromFile "https://ix.bhalash.com" "/var/www/ix.bhalash.com"

It can save some overhead on requests, and is sometimes necessary when you serve content through HTTPS from a separate domain to the webpage (as I do).

PageSpeed will also take over your cache settings unless you override it, as above. PageSpeed does a great deal out of the box to help boost a performance, but it can’t do everything. At some point you have to refactor your code: split up CSS, inline it and move JavaScript into the footer. I will tackle further server and image optimizations in the next part.