WordPress and PageSpeed Insights

Today i tested my WordPress Theme on Google’s PageSpeed Insights. The result was a little disapointing. The Desktop version scored above 90 out of 100, but the mobile version scored around 80.

Based on Google’s suggestions i searched for some solutions.

Eliminate render-blocking JavaScript and CSS in above-the-fold content

Due to my own plugin Wp Defer loading there was no render-blocking JavaScript.

@import CSS child theme

My test site runs a child theme of JBST. The stylesheet of this child theme imports the stylesheet of it’s parent by @import url(../jamedo-bootstrap-start-theme/style.css);. Although appropriate course of action following Child Themes this is a performance issue.

In the case of JBST the parent style.css contains only some empty default styles. So for child themes (of JBST) remove this @import. Also notice for the parent style.css can’t be excluded by removing wp_enqueue_style( 'jbst-style', get_stylesheet_uri() ); cause some child themes will relay on it’s own style.css instead of only LESS code (custom.less).

Plugin’s stylesheets

My test site use a Question and Asnswer plugin, i found it’s style sheet included on my front page as well. On the front page this style sheet shouldn’t load.

Prevent Plugin’s from loading

By default WordPress loads all plugins (including CSS and JavaScript) on all pages. This also mean performance can be improved at two different stages: prevent the plugin from loading at all and prevent the style sheets and JavaScript from loading.

First a found the “Selective Loading Plugin”. This plugin looks promising, but seems not to work well or at least as expected. After add the class initialization which was missing, the settings interface won’t work too. I found some plugins not loading but overall the result was not good.

After this i investigate where plugins load in WordPress’s code. Plugins load in wp-settings.php, there are no hooks for this action defined. Also the old school (and deprecated!) my-hacks.php can not overwrite the loaded plugins.

The only way to prevent plugin from loading, i found, is edit wp-setting.php itself. Plugins are load by including through iterating an array with plugin paths:

// Load active plugins.
foreach ( wp_get_active_and_valid_plugins() as $plugin )
	include_once( $plugin );
unset( $plugin );

So removing paths from this array will prevent them from loading. For my test site i found the plugin path has q-and-a in its name and the plugin should only load if the request uri contains /knowledge-base/. Based on this data i could change the preceding code into:

// Load active plugins.
$plugins = wp_get_active_and_valid_plugins();
foreach($plugins as $key=>$value)
{
if(strstr($value,'q-and-a') &&  !strstr($_SERVER['REQUEST_URI'],'/knowledge-base/')){unset($plugins[$key]);}
}
foreach ( $plugins as $plugin )
        include_once( $plugin );
unset( $plugin );

The above works well. If you know what to code, you can code it effective. You also have to remember that wp-settings.php will be overwritten when upgrading WordPress.

I also found i can’t remove every plugin this way. For example removing WooCommerce cause problems with the shopping button which should be load on every page and requires WooCommerce (global $woocommerce). Maybe a reason to load all by default.

Prevent CSS and Javascript from loading

On How can I reduce the amount of files loaded/included per plugin? i found: “Current versions of WordPress allow for enqueuing later in the flow so you you can, for example, enqueue on your shortcode init/parse.” I will test this soon, cause it seems very useful for my own plugins too.

For now i start conditional dequeue CSS an Javascript i don’t need. For example for WooCommerce this can been done effective by adding some lines to functions.php:

if(function_exists('is_shop') && !is_shop())wp_dequeue_style( 'woocommerce_frontend_styles');

Overall i found some small code changes will have a huge performance profit.

Images

Pagespeed also mentioned: “Losslessly compressing” for some PNG files used. I found OptiPNG can resolve this easy.

WordPress Development: Properly load your Javascript and set dependency

Theme and Plugin developers should wp_enqueue_script() to load the Javascript sources used in their code. Why should you enqueue? In the first place you should prevent conflict between your scripts. Secondly you should only load the resources you need per page. Load the right scripts only will reduce your load time.

WordPress offers a list of bundled resources like jQuery. So you don’t have to load jQuery every time, but you will have to set the dependency of jQuery of the sources you add.

Enqueueing you scripts proper will also help other theme and plugin developers. When two plugin need the same Javascript library you will load it only once. You will have to realize this in not guaranteed and documented well. If two plugins for example need some plugins of Twitter’s Bootstrap there will be no rules to describe the source already loaded. A solution can be both plugins depends on a third plugin which loads the resources. This kind of dependency is outside the scope of this blog post.

Although the reasons for proper loading seems clear many plugins and themes haven’t enqueued all their code.

Why do developers skip wp_enqueue_script()?

The main reason i found was the use of dynamic variables. Enqueued scripts load before the theme or plugin functions have been parsed in many situations. For example you will set the width of an element by javascript where the width will be user defined. The easiest but wrong solution will be to write it direct to source. Write javascript to source and for example make use of jQuery’s document ready will create a dependency of jQuery.

Solutions to use dynamic variables with wp_enqueue_script:

The first solution will be to write your code in native javascript not dependent of any library.
The second, and preferred solution in my opinion, is to (mis)use the wp_localize_script() function. wp_localize_script() localizes a script, but only if script has already been added. Can also be used to include arbitrary Javascript data in a page. The latest can be used to set your dynamic variables. Also read: Use wp_localize_script, It Is Awesome
Some example:

/** set parameters for display **/

$options = array();
$options[‘color’] = get_option( ‘color’, ‘blue’ );

wp_register_script( ‘color_display’, plugin_dir_url( __FILE__).’display_color.js’, array( ‘jquery’ ), ‘20131108’ );
wp_enqueue_script( ‘color_display’ );
wp_localize_script(‘color_display’, ‘color_display_options’,$options)

With display_color.js:

jQuery(document).ready(function($) {
$('colored').css('background-color',color_display_options.color);
};

Defer loading plugin

Recent i wrote a plugin for Defer loading. This plugin requires scripts are enqueued proper. Testing this i found many issues with different

plugins: