Tag Archives: WordPress
ZendCon 2017
I'm excited to once again be presenting at ZendCon 2017. This year I'll be doing two talks.
On Tuesday, October 24, I'll be presenting "Isomorphic WordPress Applications using NodeifyWP" which will cover isomorphic JavaScript in WordPress, specifically NodifyWP, Twenty Sixteen React, and the NodifyWP Environment. Here are my slides.
On Thursday, October 26, I’ll be presenting “Transforming WordPress Search and Query Performance with Elasticsearch “. This talk will cover Elasticsearch, ElasticPress and WordPress. Here are my slides:
Isomorphic WordPress Applications using NodeifyWP at WordCamp Lancaster 2017
This weekend I'll be presenting on "Isomorphic WordPress Applications using NodeifyWP". I'll also be discussing the NodeifyWP Environment – a Dockerized environment pre-setup for running NodeifyWP applications.
WordPress Best Practices for Enterprise at Music City Code
Today I'm presenting on Best Practices for WordPress in Enterprise at Music City Code 2016. Here are a few of the topics that will be covered:
- – Caching for high traffic situation
- – Security techniques
- – Writing maintainable/extensible code
- – Optimizing database reads/writes
- – Search
- Teamwork in software development
- – Browser performance
- – Workflows
- – Utilizing third party libraries
Slides for anyone who needs them:
This presentation is based on 10up’s amazing Best Practices.
post_class() and get_post_class() – Performance Killers for WordPress and WooCommerce
The get_post_class()
function is a WordPress function commonly used within post “rivers”. For example, if I had a list of posts, WooCommerce products, or any content type really, I might have some code like this:
<div >
Note: post_class()
just calls get_post_class()
and outputs it to the browser.
post_class()
will output something like class="post has-post-thumbnail type-POST-TYPE status-POST_STATUS tag-TAG1 tag-TAG2 category-CATEGORY1 category-CATEGORY2 ...."
The classes added make it easy to style content that has a specific taxonomy term, has a thumbnail, a particular status, etc.
However, the queries needed to determine all this information are not cheap. Moreover, this function is probably called for every post you’re listing. So if you have posts_per_page
set to 20, this function will be called 20 times.
Let’s take a look at the function’s code (I’ve trimmed some of the comments):
function get_post_class( $class = '', $post_id = null ) { $post = get_post( $post_id ); $classes = array(); if ( $class ) { if ( ! is_array( $class ) ) { $class = preg_split( '#s+#', $class ); } $classes = array_map( 'esc_attr', $class ); } else { // Ensure that we always coerce class to being an array. $class = array(); } if ( ! $post ) { return $classes; } $classes[] = 'post-' . $post->ID; if ( ! is_admin() ) $classes[] = $post->post_type; $classes[] = 'type-' . $post->post_type; $classes[] = 'status-' . $post->post_status; // Post Format if ( post_type_supports( $post->post_type, 'post-formats' ) ) { $post_format = get_post_format( $post->ID ); if ( $post_format && !is_wp_error($post_format) ) $classes[] = 'format-' . sanitize_html_class( $post_format ); else $classes[] = 'format-standard'; } $post_password_required = post_password_required( $post->ID ); // Post requires password. if ( $post_password_required ) { $classes[] = 'post-password-required'; } elseif ( ! empty( $post->post_password ) ) { $classes[] = 'post-password-protected'; } // Post thumbnails. if ( current_theme_supports( 'post-thumbnails' ) && has_post_thumbnail( $post->ID ) && ! is_attachment( $post ) && ! $post_password_required ) { $classes[] = 'has-post-thumbnail'; } // sticky for Sticky Posts if ( is_sticky( $post->ID ) ) { if ( is_home() && ! is_paged() ) { $classes[] = 'sticky'; } elseif ( is_admin() ) { $classes[] = 'status-sticky'; } } // hentry for hAtom compliance $classes[] = 'hentry'; // All public taxonomies $taxonomies = get_taxonomies( array( 'public' => true ) ); foreach ( (array) $taxonomies as $taxonomy ) { if ( is_object_in_taxonomy( $post->post_type, $taxonomy ) ) { foreach ( (array) get_the_terms( $post->ID, $taxonomy ) as $term ) { if ( empty( $term->slug ) ) { continue; } $term_class = sanitize_html_class( $term->slug, $term->term_id ); if ( is_numeric( $term_class ) || ! trim( $term_class, '-' ) ) { $term_class = $term->term_id; } // 'post_tag' uses the 'tag' prefix for backward compatibility. if ( 'post_tag' == $taxonomy ) { $classes[] = 'tag-' . $term_class; } else { $classes[] = sanitize_html_class( $taxonomy . '-' . $term_class, $taxonomy . '-' . $term->term_id ); } } } } $classes = array_map( 'esc_attr', $classes ); $classes = apply_filters( 'post_class', $classes, $class, $post->ID ); return array_unique( $classes ); }
Within this code, the following functions might result in database queries: get_post_format
, has_post_thumbnail
, is_sticky
, and get_the_terms
. The most expensive of these queries is get_the_terms
which for each taxonomy associated with the post type, selects all the terms attached to the post for that taxonomy. If there are four taxonomies associated with the post type being queried, get_post_class
could result in 7 extra database queries per post. With 20 posts per page, that’s an extra 140 queries per page load! On WooCommerce sites where there are many taxonomies and usually many products per page being shown, this is a huge performance killer. Yes, object caching (and page caching of course) will improve our eliminate some of the database queries, but people will still be hitting the cache cold sometimes.
Solution:
Don’t use get_post_class
or post_class
. It’s not that important. 99% of people don’t use the tags it generates. What I do is output the function, inspect the classes it adds using Chrome, and hardcode the classes actually referenced in CSS into the theme.
PS: body_class()
is much less query intensive and okay to use.
WordPress Best Practices at WordCamp Porto 2016
Today I'm presenting on Best Practices for WordPress at WordCamp Porto 2016. This talk is similar to my WordPress Best Practices for Enterprise talk but will be a bit more general and has some updated topics. Specifically, this presentation will include:
- – Caching for high traffic situation
- – Security techniques
- – Writing maintainable/extensible code
- – Optimizing database reads/writes
- – Search
- – Browser performance
- – Workflows
- – Utilizing third party libraries
Slides for anyone who needs them:
This presentation is based on 10up’s amazing Best Practices.
Simple Cache Plugin
I released a new plugin called Simple Cache.
In my blog post Comparison of Popular WordPress Caching Solutions, I rated a number of popular caching plugins pointing out what I like and dislike about each. After writing the post, I decided to create my own plugin that embodies all the characteristics that I think are best for users based on my research and years of experience in WordPress.
Simple Cache is built on the notion of “two paths”: simple and advanced. The plugin defaults to simple mode which simply allows you to turn caching on and off. It “just works” and makes your site run fast.
Advanced mode let’s you set up page caching and object caching using either Memcached or Redis. The plugin uses forked code from WP Redis, Memcached, and Batcache – all plugins that are used on enterprise WordPress websites serving millions of page views.
The plugin is developer friendly with hooks and filters. It also provides very simple and user friendly instructions, notices, field explanations, and warnings.
Give it a try and let me know what you think in the comments below.
Comparison of Popular WordPress Caching Solutions
WordPress has gotten a reputation of being, among other things, "slow". Is that true? Well, yes and no. One of the most important factors in website performance is "caching". Caching is the act of saving things that are computed often in easy to access places. For example, rather than running a tough database query every time a web page is loaded, save the results of that database query the first time it's run. When that same query is about to be run later, use the previously saved version and skip the query. WordPress does not cache "out of the box" but provides a powerful underlying API (or interface) for plugins to accomplish this. This is a dramatic oversimplification of caching and website performance but is enough for my post.
Having a properly setup caching solution in WordPress is extremely important for providing fast page loads. This post will investigate some of the popular caching solutions for standard WordPress users. I’ll make a recommendation at the end of the post to aid in choosing the right plugin for you.
Note that I am only judging basic caching functionality – page, database, and object caching. I believe, and my extensive experience working with client shows, that cramming a ton of extra features into a plugin usually results in a less effective and harder to use plugin. I recommend finding separate, more focused, plugins for CDNs, file compression, minification, etc.
All plugins have been tested with WordPress 4.4.2, nginx 1.9.9, PHP-FPM 5.5.9, MySQL 5.5.46, and Ubuntu 14.04.
I am rating each plugin on the following categories:
- Ease of Use – How easy is the plugin to use and configure for the average user?
- Clutter and Upsell Free Dashboard – Is the plugin settings page filled with links to irrelevant websites? Does it contain upsells or ads? Is the plugin settings page logically organized?
- Page Caching – How effectively does the plugin provide page caching? Page caching is the act of caching entire pages so subsequent requests receive cached versions.
- In-memory Object Caching – How effectively does the plugin provide in-memory object caching? In-memory object caching is the act of caching arbitrary chunks of data for use later in something like Memcached or Redis.
- Free Support Quality – How effective is free support being provided?
- Uninstall Clean Up – How effectively does the plugin clean up after itself? Many caching plugins add and/or modify a number of files in WordPress. These modifications and additions can cause problems if not cleaned up properly.
- Security – How secure is the plugin to run?
W3 Total Cache
Ease of Use | 2/10 |
Clutter and Upsell Free Dashboard | 2/10 |
Page Caching | 4/10 |
In-memory Object Caching | 8/10 |
Free Support Quality | 4/10 |
Uninstall Clean Up | 3/5 |
Security | 9/10 |
Overall | 4.9/10 |
W3 Total Cache does a LOT of stuff besides standard caching e.g. CDN support, Varnish, Google Page Speed, minification, site monitoring via New Relic, and more. There are a ton of options; 99% of which are not useful for most people. This makes the plugin more complicated to use.
The dashboard is cluttered with up-sells.
Disk and Memcached based page caching still resulted in MySQL queries being run according to my tests. Disk and Memcached based database query caching also still resulted in MySQL queries being run. These are either bugs or poorly explained functionality. Once I enabled the object cache, no more MySQL queries were ran.
After removing the plugin, all the cache files are left in my wp-content folder. The plugin did clean up important functional files.
A plugin audit revealed a good use of important code level security techniques such as escaping, nonces, permission checks, and sanitization. This plugin is safe to run on your website and does not make you vulnerable to hackers.
Regarding support, WP Tavern has reported some serious support concerns.
WP Super Cache
Ease of Use | 7/10 |
Clutter and Upsell Free Dashboard | 8/10 |
Page Caching | 9/10 |
In-memory Object Caching | 0/10 |
Free Support Quality | 6/10 |
Uninstall Clean Up | 5/5 |
Security | 9/10 |
Overall | 6.7/10 |
WP Super Cache keeps things pretty simple with standard functionality. I really like how it has “easy” and “advanced” tabs. Besides basic caching, it supports CDNs and a number of advanced options.
The plugin dashboard is clean and uncluttered. There are no upsells.
Static file page caching works perfectly out of the box. No MySQL queries were ran in my testing of page caching. In-memory object caching on the other hand is not supported by the plugin at all. This is a huge disadvantage as the object cache API is very powerful allowing us to cache complex queries and utilize in memory caches such as Memcached.
The plugin authors (Automattic) seem to be responding to threads in the WordPress.org support forum.
The plugin is well-written. There are no obvious security flaws.
Uninstalling the plugin cleaned up all necessary files.
WP Fastest Cache
Ease of Use | 5/10 |
Clutter and Upsell Free Dashboard | 0/10 |
Page Caching | 7/10 |
In-memory Object Caching | 0/10 |
Free Support Quality | 8/10 |
Uninstall Clean Up | 5/5 |
Security | 0/10 |
Overall | 3.8/10 |
WP Fastest Cache is somewhat easy to use. All of it’s important features are easily visible. It could be made much clearer what is needed to be done to turn on basic caching.
The plugin has filled with upsells. About half the functionality requires a premium license. However, basic caching functionality is provided for free.
Enabling caching immediately threw a PHP warning. It isn’t exactly clear the type of caching the plugin enables. Is it disk based? Is it page caching? It’s not very clear. The plugin performs disk based page caching. An option must be read in the database before static output can occur. No in-memory object caching is provided.
The plugin author seem to be responding to threads in the WordPress.org support forum.
The plugin uses nonces properly. However, it has some sanitization issues. This plugin is not completely safe for use.
Uninstalling the plugin cleaned up all necessary files.
Hyper Cache
Ease of Use | 4/10 |
Clutter and Upsell Free Dashboard | 5/10 |
Page Caching | 7/10 |
In-memory Object Caching | 0/10 |
Free Support Quality | 3/10 |
Uninstall Clean Up | 3/5 |
Security | 0/10 |
Overall | 3.3/10 |
Hyper Cache is confusing to use. There is no option to enable caching. Instead you have to click save in the settings page without changing anything. Very strange. The first option shown on the settings page is “Disable Translations” which seems pretty unimportant.
There is some clutter in the dashboard for other plugins by the author, but there are no upsells.
Up front, it isn’t exactly clear the type of caching the plugin employs. Is it disk based? Is it page caching? After testing, I found out the plugin performs disk based page caching. No MySQL queries were ran when the cached page was served. There is no in-memory object caching unfortunately.
Regarding support, the plugin author does not seem to be actively responding to support threads. There also does not seem to be community members providing support.
The plugin has serious sanitization issues and poses a security threat when installed.
Uninstalling the plugin cleaned up important functional files but did not remove everything properly.
Comet Cache
Ease of Use | 4/10 |
Clutter and Upsell Free Dashboard | 2/10 |
Page Caching | 7/10 |
In-memory Object Caching | 0/10 |
Free Support Quality | 7/10 |
Uninstall Clean Up | 4/5 |
Security | 0/10 |
Overall | 3.7/10 |
Comet Cache makes it very clear how to enable caching. This is a huge plus. Enabling caching gives me an error message to update my nginx configuration. However, after looking at the configuration updates, they are not necessary for basic caching. The plugin has a lot of useful help text. The plugin is not compatible with PHP 5.2; there fore it is not compatible with all versions of WordPress.
The plugin dashboard is cluttered with plugin author promotions as well as upsells. The clutter makes the plugin harder to navigate.
Like many caching plugins, it isn’t 100% clear what type of caching the plugin employs. After testing, I found out the plugin performs disk based page caching. No MySQL queries were run when the page cache was served. There is no in-memory object caching unfortunately.
Regarding support, the plugin authors seem to be actively involved in the support forums. There are also people volunteering their time for assisting others.
The plugin seems to properly sanitize and escape data. However, it is doing some slightly scary things with direct database queries.
The plugin has an option for uninstall method. You can either just delete the plugin or delete the plugin and all it’s data.
Recommendation
If you are looking for easy to use caching that “just works”, WP Super Cache is for you. The plugin provides disk based page caching that will dramatically speed up the vast majority of websites. The support community is vibrant, and the plugin is well maintained.
If you want in-memory object caching and don’t mind getting your hands dirty, install the Memcached and Batcache drop in plugins. Both of those plugins require manually moving files into your wp-content folder. Neither plugin has a settings page as they are both plug and play. They can be somewhat unforgiving if you run into an issue. If you want in-memory object caching but want something easier, I recommend W3 Total Cache.
Spirited comments around these recommendations as well as new ones are welcome 🙂
EDIT: Lot’s of people recommended I review WP Rocket which is a premium file based page caching plugin. Overall, WP Rocket is a solid plugin. It’s written well and “just works”. However, it is not free and only offers file based page caching. It does not support object caching. I also think the plugin’s UI could be a bit simpler.
Based on my experience with all these plugins, I wrote my own called Simple Cache. Simple Cache offers file based page caching. The plugin literally only has one setting “on or off” unless you turn on advanced mode. Advanced mode let’s you do object caching and in-memory page caching. The plugin is written securely and is extremely performant. Anyone looking for a caching plugin should give Simple Cache a try and leave me some feedback below 🙂
Custom Contact Forms 7.1 – Advanced Notifications
Custom Contact Forms 7.1 has been released. The new version contains some bug fixes for sitemap SEO, non-American date formats, and advanced notifications. Specifically, I wanted to highly the advanced notifications feature which is very powerful.
In the new version, you can create an unlimited amount of notifications which allows you to send different notifications to administrators, editors, the form submitter, etc. Here is a screenshot of the new notification editing experience:
For each of your forms, you can view notifications in list view giving you an easy way to see all your notifications:
Advanced notifications will continue to be improved in newer versions as we believe notification functionality is extremely important to web forms.
WordCamp US 2015
Today I will be presenting on Best Practices for WordPress in Enterprise at WordCamp US 2015.
If you want to follow along or missed the talk, here are the slides: