10 Micro Optimisations for a Faster WordPress Website

(Update 2019-08-07: this article is now available in Brazilian Portuguese: 10 dicas para um site WordPress mais rápido)

Website speed is a huge factor in your search engine (specifically Google) ranking:

As part of that effort, today we’re including a new signal in our search ranking algorithms: site speed. Site speed reflects how quickly a website responds to web requests.

Using site speed in web search ranking — Official Google Webmaster Central Blog

Faster websites dramatically increase the likelihood of converting a visitor into a customer:

The result of rebuilding our pages for performance led to a 40 percent decrease in Pinner wait time, a 15 percent increase in SEO traffic and a 15 percent increase in conversion rate to signup.

Driving user growth with performance improvements — Pinterest_Engineering

And a speedy website improves overall user experience (so says I; seriously.. do we really need stats to prove that slow sites piss people off?)

Most of us have heard of the generic advice – use smaller images and don’t forget to compress them, avoid too many plugins, pick a faster host, leverage browser caching. But if we’ve done all that and want to improve further, what next? How do we further optimise our WordPress websites to boost our speed, improve our responsivity and encourage Google to rank us higher?

Reduce our WordPress HTTP requests

A HTTP (hypertext transfer protocol) request is, in simple terms, a way of retrieving information from a server. When you visit a website — to look at this blog post for example — your browser asks for information relating to the page you’re looking at: images, JavaScript files, HTML files, etc. The server then sends these files back. The more files you request, the longer the server takes to respond, and the longer it takes for your web page to load.

In my experience, this is one of the most overlooked elements of optimising for speed and a great way of making ‘quick win’ improvements. So here are a whole bunch of actually implementable ways to reduce your WordPress http requests:

  1. Remove jQuery Migrate
  2. Remove wp-embed.min.js
  3. De-queue plugin styles
  4. Disable gutenberg
  5. Remove emoji support
  6. Conditionally enqueue scripts & styles

1. Remove jQuery Migrate

jQuery Migrate is a JavaScript library (collection of code) that is generally included to prevent older jQuery code from doing a ‘crash and burn’. It retains compatibility by keeping functionality that has been deprecated (removed) in the main jQuery library. In other words, if you’re running a plugin that depends on an ancient version of jQuery, or rather, an old feature of jQuery, then Migrate keeps things ticking over nicely.

However, because we’re all sensible webmasters, we keep our WordPress and WordPress plugins up to date, and that includes using plugins that have been kept up to modern ‘standards’. (You do keep your site up to date, yes? Yes.) WordPress has included jQuery Migrate by default since WordPress 3.6. As such, most of us are loading this library of old code without any actual need for it. The following snippet checks to see if jQuery migrate exists as a dependency, and if so, removes it.

function remove_jquery_migrate( $scripts ) {
	if ( !is_admin() && isset( $scripts->registered['jquery'] ) ) {
		$script = $scripts->registered['jquery'];
		
		if ( $script->deps ) {
			$script->deps = array_diff( $script->deps, array(
				'jquery-migrate'
			) );
		}
	}
}
add_action( 'wp_default_scripts', 'remove_jquery_migrate' );

Place in your theme functions.php file.

2. Remove wp-embed.min.js

When I first spotted the request to wp-embed.min.js in the head of my WordPress pages, I thought the only logical thing there is to think: oh, that must be something to do with the WordPress oEmbed support. And then I left it alone. It was a surprisingly long time before I actually checked and realised that wp-embed.min.js only actually impacts your ability to directly embed other people’s WordPress posts into your own blog, mostly thanks to this highly underrated comment.

I don’t want to embed other people’s WordPress posts in my blog, and neither do the vast majority of my commercial clients, so I turn this off using the following snippet in your theme functions.php file:

function deregister_wp_embed() {
	wp_deregister_script( 'wp-embed' );
}
add_action( 'wp_footer', 'deregister_wp_embed' );

Boom, two unnecessary http requests gone.

3. De-queue or de-register plugin styles

This one’s controversial (perhaps not as much as number 4, but we’ll build up to it) because it requires you to keep your eye on the ball for future changes. Basically, if I install a plugin on a client site that I know enqueues a stylesheet that is highly unlikely to change, or even better, is going to be overridden by my own custom CSS anyway, I dequeue the plugin stylesheet.

If I need some or all of the plugin styles retaining, I minimise the original plugin CSS and stick it as a block at the top of my main theme stylesheet so I’m not missing out. (I also do this with some JavaScript files into a central theme .js, but I’m hardcore, OK?)

This works really well for plugins like Contact Form 7, where the styles have barely ever changed and Shiftnav, a nifty mobile menu which I like to thoroughly customise for clients anyway. I’ve even done it for WooCommerce (remove and custom restyling) but that requires some heavy lifting on your part to put the pieces back together again.

Most enqueued stylesheets can be dequeued using the following snippet:

function dequeue_unnecessary_styles() {
	wp_deregister_style( 'stylesheet-id' );
}
add_action( 'wp_print_styles', 'dequeue_unnecessary_styles' );

…where stylesheet-id is the contents of id attribute in the <link />, minus the “-css”. E.g. Social Warfare’s stylesheet looks like so:

<link rel='stylesheet' id='social_warfare-css'  href='https://www.jemjabella.co.uk/.../style.min.css?ver=3.6.1' type='text/css' media='all' />

& so the stylesheet ID is “social_warfare”. You can add as many wp_deregister_style( 'stylesheet-id' ); as you like within the function.

(This might not work if the plugin author has messed with priorities, or even worse, not actually enqueued their stylesheet and injected it into the head by other means but these plugin authors need to get in the sea.)

4. Disable gutenberg & dequeue scripts/styles

Yikes, don’t get your pitchforks out. I’m slowly coming round the Gutenberg as our editor of the future, but for now there are still plenty of applications where this beast is redundant, especially for clients where the pages are so riddled with proprietary code, shortcodes and wonky widgets that its not cost effective to migrate yet. I’m yet to make the switch here on jemjabella for much the same reason (seriously, this site is ancient, don’t poke it too hard).

While a swift install of Classic Editor gets round the problem of the editing interface, for some reason (maintaining backwards compatibility in case someone attempts to use Gutenberg?) it doesn’t remove some of the Gutenberg styles and so we have to add this little snippet to functions.php to finish the job:

function deregister_gutenberg_styles() {
	wp_dequeue_style( 'wp-block-library' );
	wp_deregister_style( 'wp-block-library' );
}
add_action( 'wp_print_styles', 'deregister_gutenberg_styles', 100 );

(I had some problems doing it without the priority set originally, your mileage may vary.) Yay, bye superfluous Gutenberg http request!

5. Remove emoji styles

No big explanation needed for this one: do clients really need emoji support on their sites? No. Goodbye emoji scripts and styles.

remove_action( 'wp_head', 'print_emoji_detection_script', 7 );
remove_action( 'admin_print_scripts', 'print_emoji_detection_script' );
remove_action( 'wp_print_styles', 'print_emoji_styles' );
remove_action( 'admin_print_styles', 'print_emoji_styles' );

Place in your theme functions.php file.

6. Conditionally enqueue scripts & styles

If we take the dequeue and minify/compress styles advice one step further, we can think about those remaining plugins that we’ve left enqueuing styles as normal and figure out if/where these plugins are necessary. For example, I use Social Warfare sharing buttons on this blog but only on posts and snippets. It doesn’t, therefore, seem efficient to immediately load the Social Warfare styles on the home page (especially as my home page has a bunch of conditionally loaded JavaScript to do the OTT grid effect).

I use the following snippet to make WordPress only enqueue the Social Warfare styles on those two types of page:

function conditionally_deregister_styles() {
	if ( !is_singular( array( 'post', 'snippet' ) ) ) {
		wp_deregister_style( 'social_warfare' );
	}
}
add_action( 'wp_print_styles', 'conditionally_deregister_styles' );

(I actually combine this with the gutenberg removal code from earlier as they’re both getting in on wp_print_styles action.)

So what’s next, Jembo? What other teeny tiny optimisations can we do?

Reduce our code size

In the race to the top, every byte counts, and here are another bunch of optimisations you can make to reduce your WordPress HTML output to scrape a few more milliseconds off your load time:

  1. Remove duplicate functionality
  2. Strip WordPress menus bare
  3. Tidy up wp_head()
  4. Oh, and don’t forget…

7. Remove duplicate functionality

Yesterday I migrated from Yoast SEO to The SEO Framework after problems with Yoast retaining my configuration (amongst other reasons). In the process I realised that both The SEO Framework and Social Warfare were spitting out Open Graph & Twitter Card meta tags (and Yoast/Social Warfare would have been doing the same). I disabled Social Warfare’s og/twitter card implementation (love it when plugin authors make it easy) to let The SEO Framework do the legwork.

It did make me think, though: as we build our sites and add plugin after plugin (this blog clearly no exception) we are likely to come across instances where two plugins are covering the same functionality twice. To avoid both conflict and unnecessary code, regularly audit your plugins to see what you can turn off (either as a setting, or by getting rid of the extra plugin altogether).

8. Strip WordPress menus bare

One of my clients at one point had a ‘mega menu’ on their site with something in the region of 300 items in it. As well as regularly crashing the WordPress menu interface, this one menu alone generated thousands of bytes of code. However, most of that code was for random classes that WordPress insists on including which turn something as simple as

<li class="current-menu-item"><a href="https://www.website.com/some-page/">Some Page</a></li>

into

WTF gif

<li id="menu-item-15564" class="menu-item menu-item-type-custom current-menu-item menu-item-object-custom ss-nav-menu-item-depth-3"><a href="https://www.website.com/some-page/">Some Page</a></li>

…multiplied by 300.

All hail the wonderful Purify WP Menus. This plugin allows you to turn on and off various classes giving you back lovely, clean, optimised WordPress menus without affecting any ‘current menu item’ styling or messing up your hierarchy. Bosh!

9. Tidy up wp_head()

This is a generic tip that’s often recommended for security reasons: remove a bunch of URLs and info from the head, suddenly your website is impenetrable! TADA! Except it’s not that simple. However, you can tidy up your wp_head and remove some stuff you probably won’t need and save a few bytes in file size. Nice.

If you don’t use any of the WordPress compatible blog clients, you can use:
remove_action( 'wp_head', 'rsd_link' );

If you don’t use Windows Live Writer, you can use:
remove_action( 'wp_head', 'wlwmanifest_link' );

If you don’t want or need feeds for categories, search, tags and post comments (this doesn’t affect your main blog feed URL), you can use:
remove_action( 'wp_head', 'feed_links_extra', 3 );

And last but not least, I can’t think of any reason you need the WordPress generator meta tag, so everyone can use:
remove_action( 'wp_head', 'wp_generator' );

(These can all go in functions.php too)

10. Oh, and don’t forget…

Use smaller images and don’t forget to compress them, avoid too many plugins, pick a faster host, and leverage browser caching… ;) You’re welcome!

Lead photo by Braden Collum

Want to go further than making basic micro optimisations to your site? I offer WordPress performance optimisation as a service. Get in touch to find out more.

7 Comments

  1. Use remove_action on child theme, not parent theme. Because it will overrided everytime theme update.

  2. Excellent work. I hate relying on plugins for everything, but am no developer. Cut to the end: You’ve nudged us back into the low 90s on cheeky old Google Page Speed Insights*. Despite – interestingly – already using a fair few WP Disable / Autoptimize type plugins that offer the moon on a stick.

    *I thought I’d be clever today and test the aforementioned google page speed insights page on, ahem, google page speed insights. It scores 100 (Desktop). Felt less clever immediately.

    Anyway, totally agree re: we don’t need stats to prove slow sites piss people off! Your contribution here is most appreciated, it reminds me of back in the day ya know, circa turn of the century (1999) when the Web per se was a friendlier place. It seemed easier then to discover quirky, genuinely useful interesting content and characters than it is now, as everyone is trying way too hard to become the next Tik Tok sensation (everyone under 25 that is).

    Excellent work again AND Mrs Tagmaster used to work @ Filofax coincidentally! Tagmaster Towers is a Nestle free zone also.

    NB: You’ve earned yourself one comp Ten Year Tag (or two if you want!) they do work for cats as well as dogs ;) Just email us if you do need one. Thanks ever so much once again for your work, Tagmaster

    • Jem

      10 Aug at 9:17 pm

      Thanks – appreciate your comment. :)

      Re: reminding you of content circa 1999 – that’s probably because that’s roughly when I started blogging, and I just never got ‘with the times’ ;)

      Not sure my cats would forgive me if I tried to put a tag on them, but your offer is v kind!

  3. Ah, number four is extremely helpful! I’ll bookmark this site for later and tweak my site a bit when I’ve the patience for it (and am not babysitting five boys). As I much more prefer the emoji support by WordPress, I’m definitely keeping it. 😅 That’s a speed risk I’m willing to take.

    Thanks for sharing.~

  4. This is great! I have definitely gone through the list of standard procedures like reducing unnecessary plugins, optimizing caching, minimizing css, etc. This takes it up a notch! Or three! Thank you!

  5. This is a great tutorial. We’ve been working on a similar solution and turned it into a plugin called Falcon. That might save users some coding.

  6. Great stuff. Thanks!

Leave a Reply to Jane Cancel reply

Your email address will not be published. Required fields are marked *