[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