[wp-trac] [WordPress Trac] #12009: Add support for HTML 5 "async" and "defer" attributes

WordPress Trac noreply at wordpress.org
Fri Jun 16 10:47:45 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 2nd-        |     Focuses:
  opinion                                        |  performance
-------------------------------------------------+-------------------------

Comment (by azaozz):

 Replying to [comment:124 joemcgill]:

 > 1. Your opinion is that supporting inline after scripts is unnecessary,
 in general

 Yes. Seems it may be unnecessary for the following reasons:

 Currently the inline "after scripts" may run (be placed in the HTML
 source) long after the "main" script. Example: when using script
 concatenation (with load-scripts.php which is always used in production)
 they are outputted after the concatenated script that contains all "main"
 scripts.

 This behaviour cannot be achieved with the current patch/PR. Seems that to
 match this behaviour the "after" scripts for delayed main scripts would
 have to be executed on the `DOMContentLoaded` event, or another
 appropriate event, that ensures that all delayed scripts have finished
 executing. This could be done from PHP by wrapping each "after" script in
 a lambda JS function that would execute at the appropriate time.

 Looking further, using this method would guarantee that the "after"
 scripts will be executed after the delayed main scripts in all cases,
 regardless of when and where the inline scripts appear in the HTML.
 However as the Script Loader API is a JavaScript API (not PHP), adding
 that lambda function may be considered "too much hand-holding", as this is
 a very well known, very basic pattern in JS.

 So in practice there will be no difference (in PHP) between the "before"
 and "after" scripts as long as the JavaScript in the "after" scripts is
 written accordingly. Even more, these inline scripts can be outputted
 directly by the plugins on different PHP "actions" or with different hook
 priority. There is actually no need for plugins to add any "before" or
 "after" inline scripts in Script Loader at all as long as the JS is
 written properly. (I wouldn't call this "best practice", but it is
 possible.)

 > 2. The implementation method in the current PR for delaying inline
 scripts is unsafe

 Wouldn't call it "unsafe", just "unneeded" and perhaps a bit "weird" :)

 The question here is: do the browsers handle `<script>` tags exactly in
 the same way and with the same security restrictions like `<script type
 ="something-else">` tags? Think that wasn't the case some time ago, not
 sure now. You're right, the use of nonces seems to remove many security
 concerns.

 However the bigger problem here is that this method does not match
 (doesn't have parity with) the way "after" scripts currently work (mostly)
 in production, see above.

 > 3. Supporting `async` and `defer` could conflict with future dynamic
 module imports

 Yep, I really hope they won't, just don't have the time to fully
 investigate that now.

 > I’ve looked into the dynamic module loading you raised in
 [https://core.trac.wordpress.org/ticket/12009#comment:116 your previous
 comment] and am not seeing any incompatibility with adding support for
 adding `async` and `defer` attributes to scripts. From what I can tell,
 any scripts that are registered as modules in the future would be able to
 be written in a way that includes dynamic imports without ever needing to
 interact with the Script Loader, since all of the logic to dynamically
 import external modules would be handled within the script itself.

 Thanks for looking at this! Yes, seems that dynamic module loading will be
 a browser controlled "pure JS" thing, completely "outside" of Script
 Loader.

 > ...where data from the server is being supplied to an inline script in
 an `after` position

 Yea, this is generally "doing_it_wrong" as long as Script Loader is
 concerned. See examples from all previous inline scripts that supply data
 (like the old translated strings). While it is possible to do I'd consider
 it "bad practice" for any JS that is handled by Script Loader. Can make
 the core scripts "non-portable" for no good reason.

 > scripts in core that are currently blocking but could be delayed in the
 future

 Don't think that would ever be possible because of the edge cases. It
 would open a huuuge can of worms :)

 I'm actually thinking the current PR may need to include a way to prevent
 (and add "doing_it_wrong") cases where a plugin or theme attempts to re-
 register any core script with `async` or `defer`. Unfortunately seems this
 functionality could be used only for newly added core scripts as there's
 no way to ensure 100% back-compat for the loading and execution order.

 > Having said all that, what needs to be determined is whether the support
 for inline scripts needs to be completely removed from the implementation
 for an initial commit, or if there are further modifications that need to
 be made in order to leave that support in place.

 - Support for "before" scripts seems to be working fine.
 - As mentioned above, support for "after" scripts can either be revised to
 achieve parity with current concatenated scripts, or completely removed
 and left for themes/plugins to handle it in JS. If removed there should be
 enough documentation explaining why, and how to add inline scripts that
 would execute after the main script has finished executing. Seems the most
 appropriate way would be to run any "after" scripts on the
 `DOMContentLoaded` event.

 > Additionally, if you have any other final changes that you would like to
 see addressed before commit, please list them so we can ensure they are
 addressed.

 Do you think a method to detect when a plugin or a theme "tweaks" a core
 script to add `defer` or `async` is worth adding? Can probably see if that
 becomes common and then add it?

-- 
Ticket URL: <https://core.trac.wordpress.org/ticket/12009#comment:125>
WordPress Trac <https://core.trac.wordpress.org/>
WordPress publishing platform


More information about the wp-trac mailing list