Skip to content

requirejs/domReady.js can severely delay rendering of content #22909

Closed
@DrewML

Description

@DrewML

Preconditions (*)

  1. Have a store running with an optimal Varnish setup (aka be fast to flush the HTML from the server)
  2. Use a handler registered with requirejs/domReady.js to render some content on the page. As an example, the Private Content feature of Magento works this way, so a default Luma setup is ready to go.

I haven't tested, but I assume this problem does not exist if bundling has been used. When bundling, domReady.js will be in a bundle loaded synchronously, so DOMContentLoaded will always fire after.

Steps to reproduce (*)

  1. In the initial HTML for any page, add a non-blocking resource (async script/img/etc), and make sure the file is served with a severe delay (10+ seconds). <img src="https://httpstat.us/404?sleep=10000" /> can be used for testing. This is done to simulate real-world delays that can happen with 3rd party content
  2. Navigate to the page the 3rd party content (with the simulated delay) has been added to

Note that, after refreshing the page several times, sometimes (race condition) the private content does not render until 10+ seconds have passed.

Expected result (*)

I expect domReady.js to invoke its registered handlers at either of the following times (whichever is observed first):

  • When the DOMContentLoaded event is fired on the document
  • When document.readyState !== 'loading'

The problem right now is that, if domReady.js loads/executes after the DOMContentLoaded event has been fired on the document, the code falls back to waiting for the load event. This is bad, and was a hack for older versions of IE to avoid doing browser sniffing.

We should basically borrow jQuery's implementation of this, as we know it's supported by all our target browsers. We should not import jQuery into domReady.js, though. Just copy/paste the implementation (few LOC).

Actual result (*)

If domReady.js loads and executes after DOMContentLoaded has already fired, registered handlers will not be invoked until every pending request for a resource has completed. This includes requests for non-critical, 3rd party resources.

Example
image

What scripts/content get delayed currently by this?

Additional Info

This problem is still present in the latest version of requirejs/domReady, to support browsers that Magento does not support.

As requirejs/domReady.js is from an older library that really doesn't change much, and is a small amount of code, I'm comfortable with us basically forking the domReady loader here and changing the logic inline.

Metadata

Metadata

Labels

Component: Framework/ComponentFixed in 2.3.xThe issue has been fixed in 2.3 release lineFixed in 2.4.xThe issue has been fixed in 2.4-develop branchIssue: Clear DescriptionGate 2 Passed. Manual verification of the issue description passedIssue: ConfirmedGate 3 Passed. Manual verification of the issue completed. Issue is confirmedIssue: Format is validGate 1 Passed. Automatic verification of issue format passedIssue: Ready for WorkGate 4. Acknowledged. Issue is added to backlog and ready for developmentReproduced on 2.3.xThe issue has been reproduced on latest 2.3 release

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions