1

I am deferring JS scripts in order to optimize page load times and SEO. My code to defer scripts is something like:

add_filter(
    'script_loader_tag', // Filters the HTML script tag of an enqueued script.
    function ( $tag, $handle ) {
        return str_replace( ' src', ' defer="defer" src', $tag );
    }
);

It works fine for most scripts. However, when it defers scripts like wp-i18n, it causes the error because of the -js-after code that it tries to run before the it executes the deferred script.

<script type='text/javascript' defer="defer" src='http://192.168.1.71/wp-includes/js/dist/i18n.min.js?ver=db9a9a37da262883343e941c3731bc67' id='wp-i18n-js'></script>
<script type='text/javascript' id='wp-i18n-js-after'>
wp.i18n.setLocaleData( { 'text direction\u0004ltr': [ 'ltr' ] } );
</script>

It seems the problem is that the script is deferred in contrast to its -js-after script. I need a solution that does one of the following.

  • Skips deferring scripts that have a -js-after
  • Deferrs the js-after along with the script.

Implementing the first option using using

$data = $wp_scripts->get_data( 'wp-i18n', 'data' );

does not work because $data does not contain information as to whether the script has a -js-after. Searching for "detecting 'WordPress -js-after'" does not give any helpful results.

5
  • 2
    I'm assuming this is on the frontend? Not all javascript can or should be deferred, and js-after isn't what you should be looking for, these look to be scripts added via wp_add_inline_script. Can an inline script even be deferred? I don't think it makes sense
    – Tom J Nowell
    Aug 2, 2021 at 20:26
  • Yes this is for the frontend. enqueue of wp-i18n triggers the added inline script. When wp-i18n gets deferred, which it can be deferred, it causes the error. Is there a way to detect if a script like wp-i18n has a corresponding inline script? What should I be looking for? Should I just hard code wp-i18n not to be deferred? What about others that are similar? Aug 2, 2021 at 21:43
  • 1
    Gravityforms plugin has $assets[] = new GF_Script_Asset( 'wp-a11y' ); in form_display.php. wp-i18n is a dependency of wp-a11y. Therefore it comes out wp-i18n is enqueued on the frontend when there is a form display. Aug 3, 2021 at 15:25
  • In general, I'd probably seek to manually choose which scripts are deferred rather than attempting to defer them all and except some few - as Tom implies, it can break a lot of things. It's probably possible to discern which scripts have wp_add_inline_script()/wp_localize_script() inline dependencies by digging through the registry in the $wp_scripts global, probably at both the wp_print_scripts action as well as wp_footer.
    – bosco
    Aug 3, 2021 at 15:56
  • You defer a script if it can be loaded later. If there's a script that depends on it, then it can't be loaded later and shouldn't be deferred. Aug 4, 2021 at 10:06

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.