[wp-trac] [WordPress Trac] #12009: Add support for HTML 5 "async" and "defer" attributes
WordPress Trac
noreply at wordpress.org
Thu May 25 20:21:36 UTC 2023
#12009: Add support for HTML 5 "async" and "defer" attributes
--------------------------------------+--------------------------
Reporter: Otto42 | Owner: 10upsimon
Type: enhancement | Status: assigned
Priority: high | Milestone: 6.3
Component: Script Loader | Version: 4.6
Severity: normal | Resolution:
Keywords: has-patch has-unit-tests | Focuses: performance
--------------------------------------+--------------------------
Changes (by joemcgill):
* keywords: has-patch has-unit-tests 2nd-opinion => has-patch has-unit-
tests
Comment:
Thanks for the detailed response, @azaozz. Sounds like we’re narrowing
down on the last remaining issues to resolve.
> However imho a bigger concern is the proposed JS that handles "scripts
after". Cloning a node and injecting it in the DOM as `text/javascript` is
pretty much as bad as running that node's content with `eval()`.
I’m in total agreement with your concerns here. When testing this approach
with Content-Security-Policy, @westonruter [https://github.com/WordPress
/wordpress-develop/pull/4391#issuecomment-1536869109 discovered] that it
had a security vulnerability related to the `strict-dynamic` source
expression for which he made a [https://wp-scripts-csp-test.glitch.me/
test case]. We’ve recently replaced the original approach with one that
uses event listeners, suggested in [https://github.com/10up/wordpress-
develop/pull/62 this PR]. The revised approach is now fully compliant with
[https://csp.withgoogle.com/docs/strict-csp.html Strict CSP]. See the
[https://wp-scripts-csp-test.glitch.me/v2/ updated test case].
Regarding examples of other platforms evaluating a script of type
`text/template`, this is essentially what was done in AMP for the amp-
script component. You can see an [https://amp.dev/documentation/components
/amp-script#from-a-local-element example] of how an inline script (here of
type text/plain) is evaluated in an AMP context.
> In my opinion there should be no support for "after" scripts for scripts
with `async` and `defer`. If plugins really want to run something after a
script is evaluated, that can be handled from the JS much better.
This goes back to why inline scripts were introduced in the first place.
There needs to be a way to pass dynamic data from PHP back to static JS
scripts that can execute either before or after a registered script.
Inline scripts are the way to do this in WP, and supporting them for
async/defer would be very useful. With WordPress providing the framework
to easily attach after inline scripts to async/defer scripts, plugin
developers wouldn’t have to come up with their own solutions every time
they want to pass data to such scripts. For example, without a deferred
inline after script, passing data to a defer script would require setting
a global variable. In contrast, with a deferred inline script you could
cleanly do:
{{{#!php
wp_register_script(
'foo',
plugin_dir_url( __FILE__ ) . 'foo.js',
array(),
'0.1',
array( 'strategy' => 'defer' )
);
wp_add_inline_script(
'foo',
sprintf( 'Foo.init( %s )', wp_json_encode( getFooData() ) ),
'after'
);
}}}
Additionally, we are attempting to create safe upgrade paths for scripts
that are currently blocking to be converted to a defer or async loading
strategy. We've designed the API changes to ensure that inline scripts
added to a handle continue to be executed in the intended order when the
loading strategy changes. This removes an important backward compatibility
concern from plugin/theme developers. The only other reasonable
alternative would be to always force any scripts that have an inline
script added to it—and all its dependencies—to load with a blocking
strategy regardless of how it was registered. This is less than ideal,
which is why we’re advocating for the event listener strategy referenced
above.
> Does adding support for async and defer would make it harder or
impossible to add support for module scripts in WordPress?
This is a good question, and one I’m continuing to review, but initially I
don’t see there being a conflict here. According to
[https://html.spec.whatwg.org/multipage/scripting.html#the-script-
element:~:text=This%20is%20all%20summarized%20in%20the%20following%20schematic%20diagram%3A
the spec], any scripts added with `type="module"` are automatically loaded
using a deferred strategy, but can also support `async` if present. What’s
more is that the changes we’re proposing to the function signatures could
make adding support for `module` easier in the future by adding an
optional ‘type’ attribute to the array of options being used for loading
strategy and position (not that we need to decide on this here). For
example:
{{{
wp_register_script(
'my-module',
plugin_dir_url( __FILE__ ) . 'my-module.mjs',
array(),
'0.1',
array(
'type' => 'module',
'in_footer' => true,
)
);
}}}
If you have specific concerns we need to be aware of, please let us know.
--
Ticket URL: <https://core.trac.wordpress.org/ticket/12009#comment:113>
WordPress Trac <https://core.trac.wordpress.org/>
WordPress publishing platform
More information about the wp-trac
mailing list