Fast loading WordPress applications offer a better UX to end users, and also return better revenue via adverts – and from a developmental point of view they also feel more slick and fine-tuned.
WordPress can load very quickly, if you stick with a very minimal, bare-bones set-up and control the build of each front-end feature, but once we leverage 3rd party plugins or themes, we are mostly at the mercy of how they are put together – and in many cases performance is a lower consideration, due to how complex and unique each website combination is once all the pieces are stacked together.
One way to improve the application loading experience is to
defer the downloading and execution of assets – which are defined as render-blocking resources – a concept which is easier to understand visually, as in the graphic below from illustration from Growing with the Web:
The developers of WordPress core have provided many standardized processes to try to help reduce the technical redundancy, one of those tools is the script and style enquing system, via the top level functions wp_enqueue_style and wp_enqueue_script.
These two functions are the back-bone of a simple dependency system, which allows developers to register assets to be loaded, prioritize their load order and also to define which other assets should be loaded before the one being registered.
These enqueue system can also help to avoid duplicate assets being loaded – by checking for matching
handles and will try to ensure specific of latest versions are loaded based on the passed version parameter ( but this is not very trustworthy, as the data is often entered manually ).
Another important features of the WordPress enqueuing system is the ability to
From a distance the system seems complete enough and offers a good standardized way for developers to add assets knowing the most other developers will also follow the same path – but as always with an open system like WordPress, developers can also choose to simply bypass the process and add assets in their own way – which will be simpler for them, but less helpful for everyone else…
Adding assets becomes easy once developers are familiar with the tools available, in some cases too easy – meaning the multiple large libraries be pulled in to provide small specific functionality with ease – on a local development install load times are rarely an issue, but if these assets are not correctly optimized before deployment, the end result can cause applications to load slowly and there is nothing Google dislikes more than slow loading applications!
As mentioned earlier, when we keep things minimal and have the time and skills to develop each application feature ourselves, we also maintain a higher degree of control offer the number and size of the assets which we include – we can also optimize their inclusion in production applications via our own task runners and build steps – but what about if we pull some 3rd party systems in?
One of the other most powerful features of WordPress is hooks – filters and actions which are both defined in the core system and by developers, to allow for downstream changes to defined configuration – one such use-case is assets includes via wp_enqueue_style or wp_enqueue_script.
If you are not very familiar with the concept of hooks, it might be better to read something from the WordPress developer documentation site, or another trusted source, they are a key feature used by plugin and theme developers as they expose data and configuration at important steps in the getting or setting steps – for example as form data is collected, validated, saved and feedback returned to the user – at each step a plugin developer might provide a filter to review the state of the data and to affect all or specific parts – filters can be run both globally ( affecting all data ) or specifically ( affeting only data which matches precise requests ).
Assets pass through many filters between being enqueued in a theme or plugin and being rendered in the final html – it is possible to debug these steps to understand them, either via code to a log or using handy developer tools like the Query Monitor plugin – the two filters we will look at in more details are style_loader_tag and script_loader_tag.
style_loader_tag filter provides access to css assets which have been registered and enqued via the provided WordPress functions and has the following signature:
apply_filters( 'style_loader_tag', string $html, string $handle, string $href, string $media )
This means that the filter can pass up to 4 parameters to any function defined using the WordPress callback method
add_filter – and it should be remembered that all WordPress filters require that some data ( altered or not ) is returned to them ( which is not the case with action hooks ):
- $html ( the full html tag ready to render the asset )
- $handle ( the unique handle defined when the asset was enqueued )
- $href ( the full path to the asset with any fragments, such as the version number included )
- $media ( the css media type, typically ‘screen’ but could be any valid value )
Our aim is to review all css assets and to defer as many as possible, while also providing 2 routes to skip deferment – via a WordPress filter and also via a value passed in the enqued asset querystring.
In the Gist below we show a full working example of the
style_loader_tag function – after we’ll explain a little more about each step:
The code snippets above show how to hook a custom function into style_loader_tag and to exclude assets via 2 routes – one via the filter
q/hook/wp_enqueue_style/avoid and the other by defining a pattern in the enqueued asset – both can be used together or you can control everything via the filter method.
You will need to ensure that your local development enviroment matches exactly the set-up of your production environment, at least in term of technology, if not actual content and then run some local tests – remember, you can easily bypass the entire filter by simply commenting it out, as such:
//\add_filter( 'style_loader_tag', [ get_class(), 'style_loader_tag' ], 0, 4 );
You can see a list of all asset
handles by uncommenting the line
error_log( $handle ); and you can also preview the data provided to the filter by uncommenting the other lines – but note that the error_log function will only write to the log if debugging is enabled and defined in the wp-config.php file.
Once you have tested everything as working correctly with deferred css assets, you can deploy the updates to your production application.
In this instance, we hook our own function to the script_loader_tag filter provided by WordPress, which passed 3 params and we can again provide our own filter hook to add or remove js assets from being deferred, there is also a way to do this by passing the ‘__nodefer’ string in the $src.
Note that the script will also allow JS files to be loaded with async attributes by adding the
__js_async string to enqued assets, which might work in some cases, but which will – in most cases – change the load order of assets – so give it a try, read about the differences and see what is the best fit for your application.
Unlike with CSS, we have defined a few key JS assets which are perhaps better to not defer while the page loads, such as jQuery or Backbone, but if your own application use-case does not require these, they can also be defered to reduce the render blocking time on the page load and speed up your application load-times even more.
Note that if you defer all your css and js assets, your application will most likely render unstyled for a short time, there are two methods to work around this which we will discuss in future posts, one is to include critical css directly in the body and the other is to use a preloader.
Any questions, ask in the comments below and happy coding 🙂