Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Trigger page load listeners when no longer loading #23313

Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@
<severity value="CRITICAL"/>
<testCaseId value="MC-14765"/>
<group value="mtf_migrated"/>
<skip>
<issueId value="MC-19868"/>
</skip>
</annotations>
<before>
<!-- Login as admin -->
Expand Down
4 changes: 2 additions & 2 deletions lib/web/requirejs/domReady.js
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ define(function () {
}
}

//Check if document already complete, and if so, just trigger page load
//Check if document is no longer loading, and if so, just trigger page load
//listeners. Latest webkit browsers also use "interactive", and
//will fire the onDOMContentLoaded before "interactive" but not after
//entering "interactive" or "complete". More details:
Expand All @@ -89,7 +89,7 @@ define(function () {
//so removing the || document.readyState === "interactive" test.
//There is still a window.onload binding that should get fired if
//DOMContentLoaded is missed.
if (document.readyState === "complete") {
if (document.readyState !== "loading") {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is an issue:
This condition automatically accepts any states which may be introduced in browsers in future.
For example: some browser adds state "initializing" and it breaks Magento2 UI, because it passes this check.

I would change it to following:

document.readyState === "complete" || document.readyState === "interactive"

However it was previously done and caused issues for IE users: requirejs/domReady#1
If Magento2 doesn't support all IE versions then Ok, just add "interactive" as in code above - this is more stable version of logical statement.

BTW Google Chrome also fires "DOMContentLoaded" - it should work fine even without this change.
However, it might be that domReady.js is loaded and executed after DOMContentLoaded fired. It may happen if all static content is cached.
In this case we're waiting for readyState "complete" which makes a problem.
If you saw real improvement then probably this is the real case how it works.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've just realized how it works: domReady.js is loaded via RequireJS, this is why it is subscribing to DOMContentLoaded after it fired.
It could be improved if domReady.js added to section statically.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Me and @ihor-sviziev tested both versions on our project.
Best performance shown when domReady.js is included into section. However you need to modify it's code a bit - add package name to AMD definition:

define("domReady", function(){ ... });

Benchmark results on real project with slow 3g mode enabled in Google Chrome dev console:

  • original - first load: 61 sec, second load: 10 sec
  • changes from this pull request - first load: 27 sec, second load: 6.7 sec
  • move domReady.js to <head> - first load: 9 sec, second load: 5 sec <== best result

Timing was measured by adding following code to <head>:

require(["domReady"], function(domReady) {
	domReady(function() {
		console.log(window.performance.now());
	});	
});

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is an issue:
This condition automatically accepts any states which may be introduced in browsers in future.
For example: some browser adds state "initializing" and it breaks Magento2 UI, because it passes this check.

See my comment #25527 (comment). Specifically,

Luckily this isn't something we have to worry much about. This check is an extremely common pattern, and both the WHATWG and W3C have strong requirements to not break the web when adding new features. But it's also a fairly trivial change to update that logic in the other PR, if we did go with it.

The !== 'loading' pattern is already how jQuery's $(document).ready(cb) function works https://github.com/jquery/jquery/blob/05184cc448f4ed7715ddd6a5d724e167882415f1/src/core/ready.js#L66

Copy link
Contributor

@ihor-sviziev ihor-sviziev Jul 29, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@DrewML FYI in the latest version of jQuery it has changed
https://github.com/jquery/jquery/blob/3.5.1/src/core/ready.js#L67-L72

Maybe we need to change it also

pageLoaded();
}
}
Expand Down