Overview

No matter how fast your server and application are, users won't be able to tell that if it still takes a lot of time for the page to load. There are many front-end optimizations that can be used to speed up the load time from the moment the HTML arrives to the browser until the page is completely rendered. Most of these optimizations revolve around using image sprites, lazy loading images, minifying and concatenating JavaScript, compiling Sass into minified CSS, and spreading your static files over a content delivery network. By taking the time to properly optimize your site you can greatly minimize HTTP requests, shrink asset file sizes, and reduce latency. None of these are incredibly difficult to set up, and can speed up your site resulting in an improved user experience, more return visits and, ultimately, a greater return on investment.

Content Delivery Network (CDN)

What is it?

A CDN is a distributed system of servers that are deployed across the internet, used to serve static content including scripts, CSS, and images. Typically CDNs are geographically dispersed across the world.

Why use it?

  • It takes the load off of your application server by forcing static assets to be downloaded from somewhere else.

  • The major benefit of using a CDN is that it can serve the assets as quickly as possible to the end user, typically from the geographically closest server, thereby reducing network latency.

  • Assets are spread across multiple servers, distributing the load over multiple external servers.

  • If assets are located on more than one hostname (e.g. ww1.mysite.com, ww2.mysite.com, ww3.mysite.com), the user's browser will parallelize the downloads.

  • Reduction of network latency, distribution of external server load, and parallelized downloads will all result in quicker page loads for the end user.

Fake CDN vs. Real CDN

There are many CDN vendors out there, two of the biggest are Amazon Cloudfront or Akamai Technologies; however, these come at a cost. There is a way to set up a "fake" CDN for no cost. A fake CDN tricks browsers to think they are downloading assets from a different host name. To set one up, you will need to set up a DNS Alias (A Record) to point to your actual domain. Since a subdomain is technically considered a separate domain it frees up requests and allows for more parallelized downloads. For example, set up a DNS Alias for images.mysite.com to point to www.mysite.com, then have all of your assets load from the images.mysite.com. You can also set up different aliases for your CSS and JavaScript assets which could lead to quicker page loads due to the parallelized downloads. A fake CDN, of course, does not offer the benefit of serving assets from the geographically closest server or from multiple servers.

CDN Rewrite Plugin

The Voce Platforms team has written the CDN Rewrite plugin that makes setting WordPress up to use a CDN a fairly simple process. After installing and activating the plugin in the backend of WordPress navigate to Settings > CDN Rewrite. In this section the only required field to update is the CDN Root URL, which would include the hostname of your CDN location (e.g. ww1.mysite.com). You can optionally set up additional hostnames to host JavaScript and CSS files (e.g. ww2.mysite.com, ww3.mysite.com) which allows you to load these resources from an external URL improving the page load time by taking advantage of parallel browser requests.

Lazy Load Plugin

Lazy load images to improve page load times and server bandwidth. Images are loaded only when visible to the user.

What is lazy loading, and why use it?

Lazy loading images is a method, implemented via JavaScript, that saves both server bandwidth and lowers load times of your webpages by delaying the loading of images in the browser until they appear in the viewport (the visible area of the browser).

How the Lazy Load plugin works

  1. The Lazy Load plugin uses jQuery Sonar, a jQuery library that adds two special events to jQuery: scrollin and scrollout which detect if an element appeared in the user's viewport.

  2. The Lazy Load plugin applies a filter on the filter hook the_content using a regular expression to change all of the <img /> tags' src attribute to a 1x1 placeholder image and adds a data-lazy-src attribute to hold the image's actual source.

  3. Using jQuery, the plugin binds the scrollin to each of the elements that have the attriute data-lazy-src. When each image comes into view, it loads the data-lazy-src attribute as the img src, lazily loading all of the images.

Minifying & Concatenating JS and CSS

What is minification and concatenation, and why use it?

Minifying can drastically reduce the file size of your JavaScript and CSS, resulting in less strain on your server to serve them. Concatenating all of your JavaScript and CSS into single files will reduce the number of HTTP requests needed to load your page, resulting in quicker page loads.

How to implement minification & concatenation in WordPress?

Refer to our section on Grunt Documentation for more infomation on how to minify your JavaSript and implement Sass compiling for minifying and concatenating CSS files.

Image Compression

What is Image Compression, and why use it?

Compressing images, especially using lossless compression can drastically reduce the size of your image assets while reducing their file sizes. This will result in less strain on your server and quicker page loads.

How to implement image compression in WordPress?

Refer to our section on Grunt Documentation for more infomation on how to implement image compression.

Grunt

What is Grunt?

Grunt is an task manager built in NodeJS that can be used to automate a set of tasks that you will run regularly. It can automatically run scripts, which act essentially as plugins that are either custom developed or from the de facto plugin repository located on github.

Grunt for Front-End Improvements

The Grunt NPM repository contains a few helpful plugins for front-end developers:

  • UglifyJS (grunt plugin) is a utility that parses, minifies, concatenates, compresses and beautifies JavaScript.
  • JSHint (grunt plugin) is a tool that helps to detect errors and potential problems in your JavaScript code.
  • Imagemin Grunt plugin takes advantage of two powerful libraries, OptiPNG and jpegtran, both of which shrink the file size of images and are capable of lossless compression.
  • Compass (grunt plugin) is an open-source authoring framework for the Sass CSS preprocessor. Sass is an extension of CSS3 that adds additional functionality including nested rules, variables and more to your CSS markup. It also allows users to include additional CSS files from within CSS files, allowing us to use a single "style.css" file in WordPress installs that will make one HTTP request but include multiple stylesheets.

Basic Setup

  • The first prerequisite is to install NodeJS on your machine; if you already have it installed you can skip this step. Otherwise visit the NodeJS homepage and follow the steps for your operating system.

  • Once you have installed NodeJS, to get started with Grunt install the Grunt CLI globally issue

    npm install -g grunt-cli

Anatomy of a Grunt Project

Grunt projects require two files package.json and the Gruntfile, which are located in the root directory of the project. These should both be committed with your project's source.

package.json

This file contains the basic data about your project, including the project's name, version and dependencies. Here is an example of a package.json:

{
  "name": "my-new-project",
  "version": "0.1.0",
  "devDependencies": {
    "grunt": "latest",
    "grunt-build": "git://github.com/voceconnect/grunt-build.git#master",
    "grunt-contrib-jshint": "~0.3.0",
    "grunt-contrib-uglify": "~0.2.0"
    "grunt-contrib-imagemin": "~0.1.2"
  }
}

name and version are the name and version of your project, respectively. devDependencies is a listing of your dependencies and the version required if they are grunt itself or if they are part of grunt-contrib repository, or, the URL to the git file if they are custom built. Version accepts latest, which is self explanatory, an actual version number or a tilde version range.

Gruntfile

This file will be named either Gruntfile.js or Gruntfile.coffee, depending on its language. This file contains project and task configuration, loading of prewritten plugins and tasks along with definitions of custom tasks all defined in a module.exports wrapper function. The Getting Started and Configuring Tasks sections on Grunt's webpage document the Gruntfile extensively.

Basic Usage

If you are working with an existing grunt project, it should have a package.json and a Gruntfile located in the project's root directory. Change directory to the root of the project and issue

npm install

this will install all of the dependencies in your project. Upon a successful installation of the dependencies issue: grunt or grunt {argument}* to run the tasks in the Gruntfile.

* The {argument} settings would be set in the Gruntfile itself, examples usage of arguments would be having a Grunt command for staging / production environments, which could run different tasks, e.g. do not minify JavaScript on staging to ease debugging.

Grunt-init

Grunt-init is a scaffolding tool used to automate project creation. It will build an entire directory structure based on the current environment and the answers to a few questions. The exact files and contents created depend on the template chosen along with the answers to the questions asked.

Installing grunt-init

Assuming that you already have NodeJS installed, install grunt-init globally by issuing:

npm install -g grunt-init

Installing the Afterburner grunt-init template

The Afterburner grunt-init-wp-theme template is a grunt-init template developed by the Voce Platforms Team to speed up theme development and promote best practices by giving users a grunt project already configured to compress images, uglify and minify JavaScript, and compile Sass.

Note: grunt-init does not require a package.json file, it creates one in your destination directory based on template.js.

One Time Installation of Template

Once grunt-init is installed, place this template in your ~/.grunt-init/ directory. It's recommended that you use git to clone this template into that directory, as follows:

git clone https://github.com/voceconnect/grunt-init-wp-theme ~/.grunt-init/wp-theme

This will place the grunt-init-wp-theme in a hidden directory in your user's root directory, available to set up as many WordPress projects as you need to.

(This is assuming you are using OS X or *nix. Windows users, see the documentation for the correct destination directory path)

Usage of the Afterburner grunt-init-wp-theme template

After running the one time installation, at the command-line, cd into an empty directory where your theme is going to be located (e.g. /wp-content/themes/mytheme) and issue the following command and follow the prompts.

grunt-init wp-theme

From the that directory, then issue:

npm install

to grab all dependencies and set up Grunt.

Note that this template will generate files in the current directory, so be sure to change to a new directory first if you don't want to overwrite existing files.

Workflow for Afterburner grunt-init-wp-theme template

Brief Note

The Afterburner grunt-init-wp-theme template is set up to build both development and production environments, it is explained in further detail in Kicking off the Afterburner grunt-init-wp-theme template below.

Concat Task

This task is only run when building for development, to make debugging easier. Production runs UglifyJS.

Keep all JavaScript files installed in /%THEME_ROOT%/js and the Afterburner Grunt task will automatically concatenate each of the files and store them in a single file named {package-name}.min.js in /%THEME_ROOT%/js/.

You will just need to enqueue the /%THEME_ROOT%/js/{package-name}.min.js file in your theme (e.g. theme functions.php file).

Note {package-name} is whatever you set the project name as when you initialized the project (i.e. issued grunt-init wp-theme on the command line)

If you need to customize any of the concat task, edit the concat object's properties in the Gruntfile.js file in the root. See the github plugin page for customization options.

UglifyJS Task

This task is only run when building for production. Development runs concat to make debugging easier

Keep all JavaScript files installed in /%THEME_ROOT%/js and the Afterburner Grunt task will automatically minify and concatenate each of the files and store them in a single file named {package-name}.min.js in /%THEME_ROOT%/js/.

You will just need to enqueue the /%THEME_ROOT%/js/{package-name}.min.js file in your theme (e.g. theme functions.php file).

Note {package-name} is whatever you set the project name as when you initialized the project (i.e. issued grunt-init wp-theme on the command line)

If you need to customize any of the uglify task, edit the uglify object's properties in the Gruntfile.js file in the root. See the github plugin page for customization options.

Imagemin Task

Keep all JPG and PNG files installed in /%THEME_ROOT%/img and the Afterburner Grunt task will optimize your JPG and PNG files and replace them with your existing files.

If you need to customize any of the imagemin task, edit the imagemin object's properties in the Gruntfile.js file in the root. See the github plugin page for customization options.

JSHint Task

Keep all JavaScript files installed in /%THEME_ROOT%/js and the Afterburner grunt-init-wp-theme template will error check your JS files and fail if any errors are found.

If you need to customize any of the JSHint task, edit the jshint object's properties in the Gruntfile.js file in the root. See the github plugin page for customization options.

Compass Task

Keep all of your Sass files in /%THEME_ROOT%/sass. Keep all of your scss in /%THEME_ROOT%/scss/style.scss. To prepare an additional scss file to be imported, create the scss files in the Sass directory and make sure they begin with a trailing _ (e.g. _additional.scss).To add the actual import directive add the names of the .scss files (you do not need to include the scss extension) be sure to include a trailing underscore before the file name, for example:

@import("_additional");
@import("_additional2");
@import("grid/_mygrid");

Be sure to add these directives after the theme description boilerplate in style.scss

The task will pre-process the style.scss file and create a single style.css file in the /%THEME_ROOT%/ that will be your main css file for your theme. You will just need to enqueue the theme's style.css file in your theme (e.g. theme functions.php file).

Note: If you include non-underscored files in the import directives it will compile that file to a css file and store it in the /%THEME_ROOT%/ and you will need to enqueue those files separately in your theme (e.g. theme functions.php file).

If you need to customize any of the Compass task, edit the compass object's properties in the Gruntfile.js file in the root. See the github plugin page for customization options.

Kicking off the Afterburner grunt-init-wp-theme template

Development

To kick off a build for development, cd into the root of your project (your theme directory) and issue:

grunt

or

grunt build:development

This will kick off compass to compile the scss files, run jshint on the .js files located in /%THEME_ROOT%/js/, concatenate the js files located in /%THEME_ROOT%/js/ and minify the .png and .jpg images located in /%THEME_ROOT%/img/

Production

To kick off a build for production, cd into the root of your project (your theme directory) and issue:

grunt build:production

This will kick off compass to compile the scss files, run jshint on the .js files located in /%THEME_ROOT%/js/, concatenate and uglify the js files located in /%THEME_ROOT%/js/ and minify the .png and .jpg images located in /%THEME_ROOT%/img/.