
Don't wait for "DOM ready" for your app to start - jacobr
https://plus.google.com/116910304844117268718/posts/UkaymyuTzaF
======
javajosh
Honestly, I don't like claims like this that are offered without any support.
Why shouldn't I wait for the DOM to be ready? Am I losing performance? If so,
where are the benchmarks?

Frankly, I'm surprised a casual comment on G+ is getting any traction
whatsoever on HN.

~~~
mattmanser
The DOM loaded event can take a while to fire, there's no need to wait for it
but then you end up either sprinkling your html with script tags or firing a
script just before the end body tag. i.e. maintenance nightmare for the
former, what's the point for the latter? Neither much better than just waiting
for dom loaded.

If it is taking a while to fire, better to solve that problem than piss around
with a half built page in my experience. I experimented at one point with js
enhancing controls just after they were declared, it's honestly not worth the
effort. He'll learn.

This smacks of the bootstrap semi-colon nonsense, we all tried semi-colonless
once, it ends up a nightmare, but some mistakes the next generation need to
figure out themselves.

~~~
barclay
> better to solve that problem than piss around with a half built page in my
> experience.

Seconded. This can cause far more bugs and timing problems than it's worth.
Find out what's taking so long to fire, and fix (or defer) that.

------
gkoberger
At Mozilla, we were losing a few add-on download clicks because of the lag
from putting the JavaScript at the bottom. So, we created a tiny bit of JS
that recorded important events, which we loaded in the <head>. The queue re-
fired off the events once the JavaScript loaded.

[https://github.com/mozilla/zamboni/blob/master/media/js/impa...](https://github.com/mozilla/zamboni/blob/master/media/js/impala/preloaded.js)

~~~
voidfiles
So, the code you post requires jQuery, I am assuming, because you don't say.
Which means you would need to also include jQuery in the header. Doesn't that
seem like a waste? Also if you had jQuery already you could probably writing a
queuing system for almost all actions, and not just "important" ones.

You should take a queue from Flickr. I took a look at how they handled this,
and I think it's one the best I have seen so far.

<http://dailyjs.com/2011/11/28/flickr-async/>

The method there could actually be a small amount of code, and wouldn't
require that you load jQuery before queuing events.

~~~
cheatercheater
> because you don't say

Use the source, Luke!

------
kevincennis
"One should always start JS apps as early as possible and only delay operation
until the "DOM is ready" that want to measure dimensions, etc. (Things relying
on CSS)."

I guess the assumption here is that your script tags are placed at the end of
the document - because if your scripts are placed in the <head> and they try
to do things like getElementById (which does not "rely on CSS") before the DOM
has been parsed, you'll definitely get an error.

~~~
MatthewPhillips
You can do a lot without accessing the DOM. Assuming you have a real app, and
not just a circus of jquery event handlers, then you probably have prototypes
to instantiate, perhaps some models to load, etc.

The post is referring back to the old jquery advice of "put everything in
$(document).ready".

------
bluesmoon
This is one of the reasons YUI added the onAvailable method back in the day
(2006 IIRC). See
[http://yuilibrary.com/yui/docs/api/classes/Event.html#method...](http://yuilibrary.com/yui/docs/api/classes/Event.html#method_onAvailable)

onAvailable lets you run a piece of JavaScript once all the nodes it requires
are available. Our first iteration just checked for the existence of the node,
but that turned out to be a problem if the node was large and had several sub-
nodes. A second iteration checked that the node existed and had a nextSibling.
This meant that the node had completed loading and parsing and the browser was
now on to the next node.

This implementation naturally needed polling of the DOM, but YUI's always been
pretty smart about clubbing polling events together, and not doing too much at
the same time.

Combined with the fact that you only need to load the YUI bootstrap code up
front and let everything else load asynchronously, this can significantly
reduce download time.

I only wish YUI 2 had a better syntax that might have made it more popular.
You'll have to take the word of those of us who worked at Yahoo! at the time,
it was a huge improvement over YUI 1, and YUI 3 is far more JavaScript like
and far less Java like.

------
moonboots
Google avoids waiting for dom ready in webapps like gmail, and their closure
library [1] doesn't have the equivalent of jquery's $(document).ready() [2].

[1] <https://developers.google.com/closure/library/> [2]
[https://groups.google.com/group/closure-library-
discuss/brow...](https://groups.google.com/group/closure-library-
discuss/browse_thread/thread/1beecbb5d6afcb41)

------
joshfraser
jQuery popularized the idea of DOM ready (which is DOMContentLoaded to the
browser). DOM ready was a big improvement from what we used to do which was
waiting for the onload event to fire. It turns out the majority of the stuff
we do in JavaScript touches the DOM in some way and you can't read or
manipulate the DOM until it's ready. If you have code that doesn't touch the
DOM, then sure, you don't have to wait, but those instances are pretty rare in
the real world. The big thing to keep in mind is that both CSS and JS block
the DOMContentLoaded event. The best thing you can do is keep the CSS and JS
that blocks your rendering to a minimum. DOM ready is usually your "perceived
performance" so it's best to get there as fast as you can. Instead of trying
to get your JavaScript running before on ready, you'd be better off making
sure you only have 1 CSS file in your head, that your JavaScript is at the
bottom of the page and other standard WPO practices.

~~~
nevinera
>If you have code that doesn't touch the DOM, then sure, you don't have to
wait, but those instances are pretty rare in the real world.

Bootstrapping backbone models/collections (or any other kind of data model
prep) is the main use-case. A site that is mostly server-driven with some
javascript ux wouldn't usually care about this technique.

------
IgorPartola
Some things you could do would include firing off XHR's and creating an
unattached hierarchy of DOM nodes which could then be attached once the main
DOM is ready. This could be neat.

~~~
mikeryan
Why would you use XHR for this instead of just bootstrapping with all the DOM
nodes in place. This sounds like it would slow the page down.

Twitter is just going through a complete re-arch of their front end to stop
loading via XHR and says they're getting a 5x speed improvement

[http://www.digitaltrends.com/social-media/twitter-kills-
the-...](http://www.digitaltrends.com/social-media/twitter-kills-the-hashbang-
promises-5x-faster-page-loads/)

~~~
IgorPartola
Normally, I am a big fan of putting everything into one HTTP response.
However, if you do need to load things asynchronously, fire off as many
requests as early as possible. For example, if you are showing some kind of
real-time data and need to get the first batch in as quickly as possible, you
might not want the complexity of two different ways of delivering the same
data just to get the initial page speedup.

------
untog
I was under the impression that "DOM ready" did not wait for CSS, but that
"load" did. In fact, i was also under the impression that CSS (loaded in the
<head> at least) blocked any further processing until it's downloaded. Am I
wrong?

~~~
kevincennis
Well, "DOM ready" isn't really a thing -- but assuming we're talking
"DOMContentLoaded", then you're absolutely right. It doesn't have anything to
do with other resources (images or CSS) being loaded or not. It'll execute as
soon as the document is parsed.

As for downloading CSS -- it won't prevent your JS from executing, but it'll
block page rendering until all the stylesheets have been downloaded and
parsed.

~~~
untog
That's what I thought. Which means the original post makes very little sense-
if your <script> tags are just before </body> there's surely no real delay
between that an using DOMContentLoaded?

~~~
cramforce
The spec agrees with you, but even MDC does not:
[https://developer.mozilla.org/en/DOM/DOM_event_reference/DOM...](https://developer.mozilla.org/en/DOM/DOM_event_reference/DOMContentLoaded)

DOMContentLoaded, in all important browsers, does block to wait for CSS.
Manipulating the DOM before this event both increases the chance to make
changes before first-paint (decreases "jigger" on page load) and gives you the
chance to request more resources earlier.

~~~
kevincennis
Wow, that's a total surprise.

I guess I never really noticed this because my scripts are always included so
much later in the document than my CSS.

------
EToS
"never wait for "DOM Ready" for an application to startup"

We've linked page load times directly to lower sales funnel drop outs, I would
warn against this for some people, as you will be blocking/delaying rendering
of the DOM for code that is ultimately not impacting the UI

[https://developers.google.com/speed/docs/best-
practices/payl...](https://developers.google.com/speed/docs/best-
practices/payload#DeferLoadingJS)

------
shawndumas
How about something like this[1]?

\----

[1]: <http://blog.shawndumas.com/wait-until>

~~~
Revisor
Hey Shawn, that's interesting. I was just thinking about a similar solution
with a JS widget we're creating for our users to embed on their websites.

I have an improvement suggestion. If the client supplies their own condition,
like in your example waiting for a specific element to be loaded, what about
(optionally) disabling the check once onload happens?

As it is, a rogue condition check could run indefinitely.

~~~
shawndumas
That's a good idea.

I envisioned using it both for on-ready and for processes that might occur
after page load. Sometimes widgets don't have callbacks, or for a long running
template being shoved into the dom or some other such situation.

I could add a fourth (optional) boolean parameter -- stopOnReady; false ends
on pageLoad, true on pageReady, and null stops on condition === true.

As to a long running check; 1.) the reason I use interval, as opposed to
timeout, is that if the number of client events get heavy it will delay
invoking the condition function [1]. 2.) a getElementById is native and
trivial (in other words -- just don't do anything crazy in the condition
function).

\----

[1]: <http://ejohn.org/blog/how-javascript-timers-work/>

------
spicyj
Is there a way to achieve the same effect while keeping scripts in the <head>?
(Not saying that's the best idea, just wondering.)

~~~
crazygringo
You could have your scripts just define functions, then call all those
functions from the bottom of your <body>.

Or, using jQuery, you could probably define a custom event on the <body>, that
you trigger manually from the bottom of your <body>, and have your scripts in
the <head> listen for that event. I've never actually tried this, though.

