Created
May 1, 2022 00:57
-
-
Save jessedmatlock/a4c1e56ff4e93d5e8dacb40a0e5940af to your computer and use it in GitHub Desktop.
Creates custom script and style loading for Wordpress to all adding Defer, Async, and Lazy Load attributes
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/** | |
* Reusable loaders | |
*/ | |
$specialLoadHnds = (object) array( | |
'scripts' => (object) array( | |
'async' => array(), | |
'defer' => array() | |
), | |
'styles' => (object) array( | |
'async' => array(), | |
'asyncPreload' => array() | |
) | |
); | |
// Same signature as wp_enqueue_style, + $loadMethod as last arg | |
function wp_enqueue_style_special($handle, $srcString, $depArray, $version, $media, $loadMethod){ | |
global $specialLoadHnds; | |
array_push($specialLoadHnds->styles->{$loadMethod},$handle); | |
wp_enqueue_style($handle, $srcString, $depArray, $version, $media); | |
} | |
// Same signature as wp_enqueue_script, + $loadMethod as last arg | |
// Reminder - $inFooter should probably be false for both async and defer | |
function wp_enqueue_script_special($handle, $srcString, $depArray, $version, $inFooter, $loadMethod){ | |
global $specialLoadHnds; | |
array_push($specialLoadHnds->scripts->{$loadMethod},$handle); | |
wp_enqueue_script($handle, $srcString, $depArray, $version, $inFooter); | |
} | |
// Identical signature to wp_enqueue_style | |
function wp_enqueue_style_deferred($handle, $srcString, $depArray, $version, $media){ | |
wp_enqueue_style_special($handle, $srcString, $depArray, $version, $media, 'async'); | |
} | |
/** | |
* Custom Script and Style Enqueued stuff | |
*/ | |
/** | |
* Callback for WP to hit before echoing out an enqueued resource | |
* @param {string} $tag - Will be the full string of the tag (`<link>` or `<script>`) | |
* @param {string} $handle - The handle that was specified for the resource when enqueuing it | |
* @param {string} $src - the URI of the resource | |
* @param {string|null} $media - if resources is style, should be the target media, else null | |
* @param {boolean} $isStyle - If the resource is a stylesheet | |
*/ | |
function scriptAndStyleTagCallback($tag, $handle, $src, $media, $isStyle){ | |
global $specialLoadHnds; | |
$finalTag = $tag; | |
if ($isStyle){ | |
// Async loading via invalid mediaquery switching | |
if (in_array($handle, $specialLoadHnds->styles->async, true)){ | |
// Do not touch if already modified | |
if (!preg_match('/\sonload=|\smedia=["\']none["\']/',$tag)){ | |
// Lazy load with JS, but also but noscript in case no JS | |
$noScriptStr = '<noscript>' . $tag . '</noscript>'; | |
// Add onload and media="none" attr, and put together with noscript | |
$matches = array(); | |
preg_match('/(<link[^>]+)>/',$tag,$matches); | |
$finalTag = preg_replace('/\/$/','',$matches[1],1) . ' media="none" onload="if(media!=\'all\')media=\'all\'"' . ' />' . $noScriptStr; | |
} | |
} | |
// Async loading via preload and loadCSS - https://github.com/filamentgroup/loadCSS/ | |
else if (in_array($handle, $specialLoadHnds->styles->asyncPreload, true)){ | |
// Do not touch if already modified | |
if (!preg_match('/\srel=["\']preload|\sonload=["\']/',$tag)){ | |
// Lazy load with JS, but also but noscript in case no JS | |
$noScriptStr = '<noscript>' . $tag . '</noscript>'; | |
// Strip rel="" & as="" portion, if exist | |
$tag = preg_replace('/\srel=["\'][^"\']*["\']|\sas=["\'][^"\']*["\']/', '', $tag, -1); | |
// Add onload, rel="preload", as="style", and put together with noscript | |
$matches = array(); | |
preg_match('/(<link[^>]+)>/',$tag,$matches); | |
$finalTag = preg_replace('/\/$/','',$matches[1],1) . ' rel="preload" as="style" onload="this.onload=null;this.rel=\'stylesheet\'"' . ' />' . $noScriptStr; | |
} | |
} | |
} | |
else { | |
// Async | |
if (in_array($handle, $specialLoadHnds->scripts->async, true)){ | |
// Do not touch if already modified, or missing src attr | |
if (!preg_match('/\sasync/', $tag) && preg_match('/src=/', $tag)){ | |
// Add async attr | |
$matches = array(); | |
preg_match('/(<script[^>]+)>/',$tag,$matches); | |
$finalTag = $matches[1] . ' async="true"' . '></script>'; | |
} | |
} | |
// Defer | |
else if (in_array($handle, $specialLoadHnds->scripts->defer, true)){ | |
// Do not touch if already modified, or missing src attr | |
if (!preg_match('/\sdefer/', $tag) && preg_match('/src=/', $tag)){ | |
// Add defer attr | |
$matches = array(); | |
preg_match('/(<script[^>]+)>/',$tag,$matches); | |
$finalTag = $matches[1] . ' defer' . '></script>'; | |
} | |
} | |
} | |
return $finalTag; | |
} | |
// BE CAREFUL OF PRIORITY | |
add_filter('script_loader_tag',function($tag, $handle, $src){ | |
return scriptAndStyleTagCallback($tag, $handle, $src, null, false); | |
},10,4); | |
add_filter('style_loader_tag',function($tag, $handle, $src, $media){ | |
return scriptAndStyleTagCallback($tag, $handle, $src, $media, true); | |
},10,4); | |
// Include in Functions.php using: | |
$special_enqueue = get_template_directory() . '/special_enqueue.php'; | |
if ( is_readable( $special_enqueue ) ) { | |
require_once $special_enqueue; | |
} | |
// Then use for styles or scripts like so: | |
wp_enqueue_style_special( 'bootstrap', 'https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/5.1.3/css/bootstrap.min.css', array(), $theme_version, 'all', 'async' ); | |
wp_enqueue_script_special( 'jqueryjs', 'https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js', array(), $theme_version, true, 'async'); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment