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

Already on GitHub? Sign in to your account

Executing scripts before load #463

Closed
smith opened this Issue Sep 15, 2012 · 3 comments

Comments

Projects
None yet
2 participants

smith commented Sep 15, 2012

Perhaps I'm not clear on the loading semantics of requirejs, jQuery, and the domReady plugin, or I'm doing something wrong, or this is a bug. If I have HTML like:

<script>
  window.onload = function () { console.log('load'); }
  document.addEventListener('DOMContentLoaded', function () { console.log('ready'); });
</script>
<script src="require.js" data-main="main.js"></script>
<img src="http://1.1.1.1/img.jpg" />

And a main.js like:

require(["domReady", "jquery"], function (domReady, $) {
    console.log('required');                                                                                                                                                      
    $(function ($) { console.log("$"); });
    domReady(function () { console.log("domReady"); });
});

And let's say the image is hosted on the moon, or Go Daddy, and loads really slowly, then in the console I get:

ready
required

... wait 30 seconds until the image times out...

load
domReady
$

RequireJS has clearly loaded all of its dependencies and is executing scripts, but the functions that are supposed to execute when the DOM is ready don't fire until the load event happens. In production my scripts may or may not be loaded when DOMContentLoaded fires so we need to wait for the event, but waiting for the load event slows things down quite a bit, especially when other resources load slowly.

This was happening using jQuery and RequireJS, so I tried the domReady plugin and it seems to behave the same way.

Am I doing something wrong here or is there a workaround to make this work?

Thanks.

Owner

jrburke commented Sep 17, 2012

The only thing I can think of is that domReady (or jQuery if using its ready()) are getting loaded after DOMContentLoaded is triggered, and the document.readyState has not been set to "complete" yet, which would indicate to domReady/jQuery that DOMContentLoaded as fired. In that case, I believe both domReady and jQuery will just bind to the window.onload handler.

I think this is the case with some newer webkit engines -- most browsers will set readyState to 'complete' but I think some webkit engines stay in 'interactive' a bit longer now.

You can try to verify if this is the issue by putting log statements in the domReady.js and jquery.js files near where they do domcontentloaded detection, to see if those console.logs get printed out after the 'ready' console message. If so, then what I described above is likely the problem.

If that is the issue, then I'm not sure of an underlying fix. When I tried to also use 'interactive' to indicate that DOMContentLoaded was reached for domReady.js, that lead to other problems.

smith commented Sep 17, 2012

Looks like you're right. And this was fixed in jQuery 1.8.0 but reverted in 1.8.1 because it could cause IE to fire the ready event too early. See http://bugs.jquery.com/ticket/10067 and http://bugs.jquery.com/ticket/12282.

I tried loading jQuery first to make sure it was loaded before DOMContentLoaded, but that didn't help since I was still calling .ready after DOMContentLoaded and before window.load.

Hopefully this report can help improve the domReady plugin in some way.

Any suggestions at this point? In the production app I'm working on the script doing this seems to load very near to the instant that DOMContentLoaded fires, so there's a chance the script will execute too early, but if we wait until the load event it's almost a 1s delay in optimal conditions and disastrous otherwise.

I suppose this issue can be closed since the underlying issue is with domReady and jQuery, but any ideas would help.

Owner

jrburke commented Sep 17, 2012

Thanks for the additional info from the jQuery project.

I would probably either:

  1. put the script tag for requirejs that has the data-main attribute at the end of the body tag. If you have your full DOM already inlined, then you should be safe to modify the DOM as soon as the app module loads.

  2. Load the images via javascript: wait until domcontentloaded/window.onload fires, then trigger the image loading.

@jrburke jrburke closed this Sep 17, 2012

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment