SEO gurus and website owners became paranoid with Page Insights’ issues lately. Although most of them simply refuse to understand how a 100% optimization may affect the number of features they still want their sites to show, they keep asking devs to fix them all.
When it comes to WordPress websites, particularly those using sophisticated plugins, deferring or running JS asynchronously sometimes prevent snippets, blocks or even entire pages to render properly.
Yes, we can still fix the dawn issues from Page Insights, but for getting a 100%, your clients need to compromise. Having that said, it is possible (and in fact simple) to have all JS scripts deferred or async in the frontend.
Never in the backend
First and foremost, forget about using this kind of snippet for backend JS dependencies. We don’t need the backend to meet the Google’s freak 100%, and messing up with admin dependencies may and probably will prevent a lot of tools and features to run.
Editors like the block editor (WP current native editor), Elementor, WP Bakery and a dozen of others won’t work the way you expected – and sometimes won’t even open. So, first of all, make sure you are restraining any changes to the frontend.
For manipulating the script tags, we will need a function – inside it, all changes will be done inside a condition:
function async_enqueue($tag, $handle) {
if(!is_admin()) {
// Changes to script tags
}
return $tag;
}
As a general rule, now you can either defer or load asynchronously all enqueued JS in the frontend. For such, the only you need to do is to add one of those lines inside the previous condition, and trigger the function using the right filter.
// For deferring all JS
return str_replace( '<script ', '<script defer ', $tag );
// For loading all JS asynchronously
return str_replace( '<script ', '<script async ', $tag );
// After that, hook the function in the following filter
add_filter('script_loader_tag', 'async_enqueue', 10, 2);
A quick remind
As previously mentioned, some features from complex plugins may not work as expected when you defer or load the JS like this. If something goes wrong, just add new conditions to your function to keep any JS file loaded as usual.