I have various javascripts that are necessary plugins in one of my WordPress domains, and I know where in the php file it\'s called from.
I\'m taking every measure I
I believe it's bad practice to defer/async WordPress jQuery. Better solution would be to exclude jQuery from the filter:
if (!is_admin()) {
add_filter( 'script_loader_tag', function ( $tag, $handle ) {
if ( strpos( $tag, "jquery.js" ) || strpos( $tag, "jquery-migrate.min.js") ) {
return $tag;
}
return str_replace( ' src', ' async src', $tag );
}, 10, 2 );
}
You can use defer
instead of async
Very little modification code Mike Kormendy, which allows you to add 2 attributes at once:
// Async load
function add_asyncdefer_attribute($tag, $handle)
{
$param = '';
if ( strpos($handle, 'async') !== false ) $param = 'async ';
if ( strpos($handle, 'defer') !== false ) $param .= 'defer ';
if ( $param )
return str_replace('<script ', '<script ' . $param, $tag);
else
return $tag;
}
Result:
<script async defer type='text/javascript' src='#URL'></script>
This blog post links to two plugins of interest:
Asynchronous Javascript
Improve page load performance by asynchronously loading javascript using head.js
WP Deferred Javascripts
Defer the loading of all javascripts added with wp_enqueue_scripts, using LABJS (an asynchronous javascript library).
Haven't tested them but checked the code and they do pretty fancy stuff with WordPress scripts enqueuing process.
But then WPSE comes to rescue:
// Adapted from https://gist.github.com/toscho/1584783
add_filter( 'clean_url', function( $url )
{
if ( FALSE === strpos( $url, '.js' ) )
{ // not our file
return $url;
}
// Must be a ', not "!
return "$url' defer='defer";
}, 11, 1 );
Trying to keep things somewhat modular and all encompassing, the following approach dynamically chooses how to embed the tag with the async or defer attributes by just appending a small identifier to the $handle name:
/**
* Add async or defer attributes to script enqueues
* @author Mike Kormendy
* @param String $tag The original enqueued <script src="...> tag
* @param String $handle The registered unique name of the script
* @return String $tag The modified <script async|defer src="...> tag
*/
// only on the front-end
if(!is_admin()) {
function add_asyncdefer_attribute($tag, $handle) {
// if the unique handle/name of the registered script has 'async' in it
if (strpos($handle, 'async') !== false) {
// return the tag with the async attribute
return str_replace( '<script ', '<script async ', $tag );
}
// if the unique handle/name of the registered script has 'defer' in it
else if (strpos($handle, 'defer') !== false) {
// return the tag with the defer attribute
return str_replace( '<script ', '<script defer ', $tag );
}
// otherwise skip
else {
return $tag;
}
}
add_filter('script_loader_tag', 'add_asyncdefer_attribute', 10, 2);
}
Example usage:
function enqueue_my_scripts() {
// script to load asynchronously
wp_register_script('firstscript-async', '//www.domain.com/somescript.js', '', 2, false);
wp_enqueue_script('firstscript-async');
// script to be deferred
wp_register_script('secondscript-defer', '//www.domain.com/otherscript.js', '', 2, false);
wp_enqueue_script('secondscript-defer');
// standard script embed
wp_register_script('thirdscript', '//www.domain.com/anotherscript.js', '', 2, false);
wp_enqueue_script('thirdscript');
}
add_action('wp_enqueue_scripts', 'enqueue_my_scripts', 9999);
Outputs:
<script async type='text/javascript' src='//www.domain.com/somescript.js'></script>
<script defer type='text/javascript' src='//www.domain.com/otherscript.js'></script>
<script type='text/javascript' src='//www.domain.com/anothercript.js'></script>
Thanks to @MattKeys @crissoca for inspiring my answer here.