[wp-trac] [WordPress Trac] #58632: Add support for 'async' and 'defer' loading to script that use inline scripts.
WordPress Trac
noreply at wordpress.org
Thu Nov 16 18:47:50 UTC 2023
#58632: Add support for 'async' and 'defer' loading to script that use inline
scripts.
-------------------------------+------------------------------
Reporter: joemcgill | Owner: (none)
Type: enhancement | Status: new
Priority: normal | Milestone: Awaiting Review
Component: Script Loader | Version:
Severity: normal | Resolution:
Keywords: needs-patch close | Focuses: performance
-------------------------------+------------------------------
Changes (by westonruter):
* keywords: needs-patch => needs-patch close
Comment:
@jg-visual Given that the gtag script is designed to be asynchronous, the
inline script can actually be placed anywhere in the page, either before
or after the gtag script. That's what this `window.dataLayer || []` bit of
code is about. So you can do this:
{{{#!php
<?php
wp_enqueue_script(
'gtag',
'https://www.googletagmanager.com/gtag/js?id=G-00000000',
array(),
null,
array( 'strategy' => 'async' )
);
wp_add_inline_script(
'gtag',
"
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', 'G-00000000');
",
'before'
);
}}}
And this will get rendered successfully as async:
{{{
<script id="gtag-js-before">
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', 'G-00000000');
</script>
<script src="https://www.googletagmanager.com/gtag/js?id=G-00000000" id
="gtag-js" async data-wp-strategy="async"></script>
}}}
On the other hand, if the external script was not designed to be
asynchronous:
{{{#!php
<?php
wp_enqueue_script(
'foo',
'https://www.example.com/foo.js',
array(),
null,
array( 'in_footer' => true )
);
wp_add_inline_script(
'foo',
sprintf( 'Foo.init( %s );', wp_json_encode( get_my_foo_args() ) ),
'after'
);
}}}
If you want to use a delayed loading strategy (namely `defer`) you can
also still do this, by wrapping the `before` inline script in a
`DOMContentLoaded` event handler:
{{{#!php
<?php
wp_enqueue_script(
'foo',
'https://www.example.com/foo.js',
array(),
null,
array( 'strategy' => 'defer' )
);
wp_add_inline_script(
'foo',
sprintf( 'document.addEventListener( "DOMContentLoaded", () =>
Foo.init( %s ) );', wp_json_encode( get_my_foo_args() ) ),
'before'
);
}}}
So you can see that to port an existing blocking script with an inline
after script to use a delayed strategy, you have to: (1) move the inline
script from `after` to `before`, and (2) wrap the code in the inline
script with a `DOMContentLoaded` event handler. This should work in the
majority of cases.
Now, as to whether we should implement automatic support for delaying
inline after scripts for delayed scripts, it turns out that usage of after
scripts is not particularly high. I [https://github.com/GoogleChromeLabs
/wpp-research/pull/64 queried HTTP Archive] for all inline scripts being
used in WordPress, and 86%+ are before inline scripts (`65.26%` via
`wp_localize_script()` and 21.29% via `wp_add_inline_script()`). Only
9.84% are after inline scripts.
Even though I worked a lot on this feature which got pulled from 6.3, I
don't think at the present time there is a real need to implement delayed
inline after scripts. I suggest we close this as `maybelater`.
--
Ticket URL: <https://core.trac.wordpress.org/ticket/58632#comment:3>
WordPress Trac <https://core.trac.wordpress.org/>
WordPress publishing platform
More information about the wp-trac
mailing list