I revised the answer once more because I recently noticed how the Twenty Twenty developers use the script_loader_tag
hook to add async
and defer
to the <script>
tag for the theme scripts.
In twentytwenty_theme_support()
in functions.php
, lines #139 & #140:
$loader = new TwentyTwenty_Script_Loader();
add_filter( 'script_loader_tag', array( $loader, 'filter_script_loader_tag' ), 10, 2 );
In twentytwenty_register_scripts()
in functions.php
, lines #208 & #209:
wp_enqueue_script( 'twentytwenty-js', get_template_directory_uri() . '/assets/js/index.js', array(), $theme_version, false );
wp_script_add_data( 'twentytwenty-js', 'async', true );
And in the TwentyTwenty_Script_Loader
class:
public function filter_script_loader_tag( $tag, $handle ) {
foreach ( [ 'async', 'defer' ] as $attr ) {
if ( ! wp_scripts()->get_data( $handle, $attr ) ) {
continue;
}
...
}
return $tag;
}
So what I'm trying to say/suggest, is that you should probably better off use the wp_script_add_data()
to add/register the custom HTML attributes (e.g. async
) for your scripts and use the wp_scripts()->get_data()
to check if the <script>
tag should be added with the custom HTML attributes, without having to manually specify the handle (e.g. your wpfrank-ptbw-pinit-js
).
And here's an example based on the above approach, where I'm registering a list of custom or extra HTML attributes for a script using wp_script_add_data( '<handle>', 'html_attrs', [ list here ] )
. Additionally, I'm using PHP's DOMDocument
for a more precise result, although str_replace()
or preg_replace()
would also do.
add_action( 'wp_enqueue_scripts', 'my_register_scripts' );
function my_register_scripts() {
wp_enqueue_script( 'wpfrank-ptbw-pinit-js', PTBW_PLUGIN_URL . 'assets/js/pinit.js', array( 'jquery' ), '', true );
wp_script_add_data( 'wpfrank-ptbw-pinit-js', 'html_attrs', [
'async' => 'async',
'defer' => true,
'data-pin-hover' => 'true',
] );
}
add_filter( 'script_loader_tag', 'my_filter_script_loader_tag', 10, 2 );
function my_filter_script_loader_tag( $tag, $handle ) {
$attrs = wp_scripts()->get_data( $handle, 'html_attrs' );
// Bail if the script doesn't have any registered custom HTML attrs.
if ( empty( $attrs ) || ! is_array( $attrs ) ) {
return $tag;
}
$dom = new DOMDocument;
//$tag = mb_convert_encoding( $tag, 'HTML-ENTITIES', 'UTF-8' );
$dom->loadHTML( $tag, LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD );
$node = $dom->getElementsByTagName( 'script' )[0];
foreach ( $attrs as $key => $value ) {
$node->setAttribute( $key, $value );
}
return $dom->saveHTML();
}