jqLite "document ready" implementation causes lazy-loaded apps bootstrap to be delayed after window.onload #15690
Description
Do you want to request a feature or report a bug?
Report a bug
What is the current behavior?
jqLite current "document ready" implementation uses DOMContentLoaded
with window.onload
as a fallback.
function jqLiteReady(fn) {
function trigger() {
window.document.removeEventListener('DOMContentLoaded', trigger);
window.removeEventListener('load', trigger);
fn();
}
// check if document is already loaded
if (window.document.readyState === 'complete') {
window.setTimeout(fn);
} else {
// We can not use jqLite since we are not done loading and jQuery could be loaded later.
// Works for modern browsers and IE9
window.document.addEventListener('DOMContentLoaded', trigger);
// Fallback to window.onload for others
window.addEventListener('load', trigger);
}
}
If the current behavior is a bug, please provide the steps to reproduce and if possible a minimal demo of the problem via https://plnkr.co or similar (template: http://plnkr.co/edit/tpl:yBpEi4).
- Load your code asynchronously (e.g., using SystemJS), to unblock the critical rendering path, and manually bootstrap an Angular app:
angular.element(function() {
angular.bootstrap(document.getElementById('myApp'), ['myApp']);
}
-
Have something else delay the
window.onload
event, e.g. a tracking script inserting a pixel into the DOM -
Because the former code is checking for
window.document.readyState === 'complete'
, the Angular app won't be bootstrapped until afterwindow.onload
, potentially causing several seconds of delays.
Unfortunately I can't create a plunker for it as plunker always execute code after the load event.
What is the expected behavior?
According to https://html.spec.whatwg.org/multipage/dom.html#current-document-readiness, document.readyState
:
Returns "loading" while the Document is loading, "interactive" once it is finished parsing but still loading sub-resources, and "complete" once it has loaded.
What is the motivation / use case for changing the behavior?
As after DOMContentLoaded
the document is interactive
, checking for readyState === 'complete'
is incorrect and forces asynchronously loaded Angular apps to wait for the - potentially far away - window.onload
event.
The jQuery "document ready" implementation itself had a similar bug, which has been fixes in jquery/jquery@dabd5ba. Apparently IE9/IE10 readyState
implementation is buggy and one has to rely on document.readyState !== "loading" && !document.documentElement.doScroll
instead of readyState === 'interactive'
.
Which versions of AngularJS, and which browser / OS are affected by this issue? Did this work in previous versions of AngularJS? Please also test with the latest stable and snapshot (https://code.angularjs.org/snapshot/) versions.
All versions of AngularJS & all browsers