Skip to content
This repository was archived by the owner on Apr 12, 2024. It is now read-only.
This repository was archived by the owner on Apr 12, 2024. It is now read-only.

jqLite "document ready" implementation causes lazy-loaded apps bootstrap to be delayed after window.onload #15690

Open
@laurentgoudet

Description

@laurentgoudet

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 after window.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

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions