Scripts in Head or at end of Document? Pros / Cons


#1

I'm new to JavaScript, and my initial understanding is that it's better to link to external scripts in the head of the document rather than at the end of the document. There are hassles with <head> links, though, such as having to prevent the script running until the page is loaded.

Often I see scripts linked near the end of the <body> section, which seems to have some advantages.

Would anyone be interested in listing / discussing the pros and cons of both approaches? Is linking to scripts at the bottom of the <body> a bad thing? I'm interested in this not only from a convenience point of view but also from a best-practice angle.

Interested in any replies or links to other discussions. smile


#2

I put locally hosted scripts in the head of the document, compressed when they're any significant size. Minimize the number of files when possible to reduce the number of requests the browser has to make to the server. My reasons for that are:

1) It just seems more tidy to have all the scripts in one place
2) I usually use a CMS or framework that handles putting the necessary scripts for a page in the head, pasting them into the body of individual pages makes it harder to keep track of them

Externally hosted scripts usually go at the end of the document so that they don't prevent your page from loading if the external server is slow. This is common for things like web stats / counters and conversion tracking code.


#3

Thanks for the reply, Dan.

In the CMSs I've used, it wouldn't be a problem to have the script links in an include which could be placed at the bottom of a template. But I guess it's a bit messier.

I don't understand window.onload fully, but it seems a little strange to me that workarounds are needed if you want to have more than one function triggered on page load. That's partly why I've started to question links going in the head section. It seems window.onload can be dispensed with if the scripts are loaded last. Or is that a misconception?

I'm starting to wonder if a decision should be made on a script by script basis. Some scripts need to be loaded before the page loads (like jQuery?), while others are better loaded after the page content.

Looking forward to more opinions on this.


#4

What gave you that idea? JavaScript gurus like Chris Heilmann are saying that putting script tags just before the </body> is optimal for performance, and it eschews the need for onload event handlers.

The only reason to put scripts in the head these days is probably if you have a server-side app that generates bits of each page in different places (e.g., Java frameworks like JSF or Seam) and your templates are not constructed properly.


#5

Heh heh, good question. I double-checked the books I have before starting this thread (such as Simply JavaScript), and they all direct you to place external links in the <head> section. I couldn't find a mention of placing them anywhere else, as if the idea is unthinkable. Yet I'm seeing the pre </body> more and more, and hence the question.

JavaScript gurus like Chris Heilmann are saying that putting script tags just before the </body> is optimal for performance, and it eschews the need for onload event handlers.

Interesting. I will look him up, because this is what I've been wondering. I wanted to hear a 'reputable' guru saying it. (Now I've heard two!)

The only reason to put scripts in the head these days is probably if you have a server-side app that generates bits of each page in different places (e.g., Java frameworks like JSF or Seam) and your templates are not constructed properly.

Very interesting. Thanks Tommy! This is very interesting. smile


#6

There's some scenarios well served by putting (some) javascript in the head, but generally, I put it all at the end of the doc.


#7

Are you able to list any of those? I'd find it interesting to have a list for future reference. I was wondering about things like jQuery, but it might depend on what it's being asked to do, I suppose.


#8

Here's an on-topic question for the JS gurus: If a script contains code that runs when the DOM is ready (e.g. jQuery's $(document).ready), and this script is included at the end of the document, might the DOM-ready trigger fire before the script has loaded, thus never running?


#9

When I first started years ago I put my javascript all over the place, including lots of inline script. ... Progress due to maintenance nightmares. I started to reference external javacript files from script tags in the head. This was so functions would be available for the remaining inline function calls when the DOM loaded in. I have since removed inline function calls from my mark-up. But for the longest time it just didn't "feel right" referencing js files anywhere other than the head. I guess part of me felt it was taking a step backwards or something.

Just as where my earlier inline function calls needed the script to already have been loaded, I eventually noticed that some scripts needed the DOM to be loaded (eg. getElementById('wrapper')) and I needed to use onload().

Right now I do something like

function doStuffA(){}
function doStuffB(){}
function doStuffC(){}
function init(){
doStuffA();
doStuffB();
doStuffC();
}

referenced in the head. And I have
onload = init; and Google analytics before the closing body tag.

I forget now and I imagine things have changed some, but I remember reading about there being browser differences in what sequence things loaded in. But I guess the main thing is to determine what needs what to be already loaded in when it's needed.


#10

Sometimes you just don't want to wait for the entire page to load to add certain javascript behavior. Of course, adding too much js too early will slow the page down too. Having the ui drastically change when the page finishes loading when js kicks in to enhance it isn't ideal imo. A page can take a long time to load for some people on certain devices.

You can usually get a good compromise by just getting the right styles loading early so the ui will be progressively rendering as the suitable js or non-js ui. But, sometimes things are more complicated and css and noscript solutions are messy.

You might even find it nice to have a small javascript widget up and running asap as the page loads. For example, I personally like it when the js nav menu is usable right away before the rest of the page loads.


#11

If I understand you right, the event shouldn't trigger if the script was actually in the html. If you loaded it via other means, ya it could fire before your script gets executed.

Regardless, your function will get called. It checks if the event already fired, and either queues your function up with any others that might have been queued, or just calls it.


#12

I can't answer your question, but why would you want to do something that stupid? If the script is at the end of the document, you don't need the event handlers to start the script.

But since the <script> tag is part of the DOM, my guess is that the DOM-ready even would occur after the the script has been loaded and executed.

In my eyes it's a moot question, though, since there's no reason to use the event if the script is already after the content.


#13

Here's an on-topic question for the JS gurus: If a script contains code that runs when the DOM is ready (e.g. jQuery's $(document).ready), and this script is included at the end of the document, might the DOM-ready trigger fire before the script has loaded, thus never running?
While Tommy's comment is of course the voice of reason, I made a test case to see what happens:

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN">
<html>
<head>
  <title>Testing ondomcontentloaded</title>
  <script type="text/javascript">
    function addP(txt) {
      var li = document.createElement('li');
      li.appendChild(document.createTextNode(txt));
      document.getElementById('stages').appendChild(li);
    }
    document.addEventListener('DOMContentLoaded', function() {
      addP('DOMContentLoaded from head');
    }, false);
    window.onload = function() {
      addP('window.onload');
    }
  </script>
</head>
<body onload="addP('body onload attribute')">
<h1>when exactly does DOMContentLoaded fire?</h1>
<ol id="stages">
</ol>
<script type="text/javascript">
addP('before domcontentloaded trigger at body bottom');
</script>
<script type="text/javascript">
document.addEventListener('DOMContentLoaded', function() {
  addP('DOMContentLoaded from body bottom');
}, false);
</script>
<script type="text/javascript">
addP('after domcontentloaded trigger at body bottom');
</script>
</body>
<script type="text/javascript">
document.addEventListener('DOMContentLoaded', function() {
  addP('DOMContentLoaded after closing body tag');
}, false);
</script>
</html>
<script type="text/javascript">
document.addEventListener('DOMContentLoaded', function() {
  addP('DOMContentLoaded after closing html tag');
}, false);
</script>

(yes, I know the last two <script>s are very wrong)

Results:

  1. before domcontentloaded trigger at body bottom
  2. after domcontentloaded trigger at body bottom
  3. DOMContentLoaded from head
  4. DOMContentLoaded from body bottom
  5. DOMContentLoaded after closing body tag
  6. DOMContentLoaded after closing html tag
  7. body onload attribute

It seems like DOMContentLoaded fires right after absolutely everything in the HTML source has been parsed, but before window.onload, which as Tommy said (regarding <script> being a part of the DOM) makes sense.

Interestingly, having an onload="" attribute in the <body> overwrites window.onload in javascript (at least in FF3.6) - even if the attribute is empty or wrong. Hence why window.onload isn't part of the results. I wasn't expecting that to happen, but I suppose it makes sense.

So anyway, DOMContentLoaded can be used anywhere, stupidly or otherwise. wink


#14

Hmmm very interesting question and answers! I've seen this a few times on some blogs as well about referencing external JS files at the bottom of the page (before the closing body tag) but I've always referenced external JS files in the head because that's what books encourage and it's what most people seem to do.

I guess I'd like to add a question to this thread. Which way should you reference external JavaScript files? In the head of the document or at the bottom of the document before the closing body tag?

If there isn't a defined way in which you should reference external JS files (and referencing them in the head is just the most popular way) then which would you recommend?

Andrew Cooper


#15

Andrew, how are your questions any different to Ralph's original, and how are they not answered already?


#16

Ralph is asking for the advantages / disadvantages of these methods and views on them from other members. I'm asking for confirmation on which method should be used, as in the standard method? There are different methods for inserting markup / content into HTML documents from external JS files such as innerHTML and createElement() and createTextNode() and both methods are used widely but innerHTML isn't a standard, although most people would use innerHTML.

I know most people reference external JS files in the head of the HTML document, but JS gurus reference it before the closing body tag but this may just be for performance increases, it may not be the standard way of referencing an external JS file. So yea, I'm asking for confirmation on which method should be used.

And the second question is me asking what method should be used if neither of them are a set standard for referencing external JS files.

Andrew Cooper


#17

Another consideration is that unlike other files where the browser can download between two and eight files at once, whenever the browser starts downloading a JavaScript file everything else stops until the browser finishes downloading that file.

If you care going to place JavaScript of more than a half dozen lines of code in the head of the page then you should replace that code with JavaScript that adds the script tags to the head dynamically so that the JavaScripts are downloaded dynamically by JavaScript itself and not by the browser. That way they do not hold up the downloading of the other files AND multiple JavaScripts can download at the same time because the one file at a time limit only applies to JavaScript downloaded directly by the browser.

You avoid that issue if you place the scripts at the end of the body.

At the end of the body you no longer need to test for if the DOM has loaded if the page is HTML because any element in the HTML DOM can be accessed immediately that element has loaded without waiting for the rest of the page. It is only with XHTML that the entire DOM is inaccessible until everything has loaded.


#18

Is it really that stupid just to ask a question?

1) Maybe I'd like to take some advice here and move scripts to the end of the document without rewriting them

2) Just about every jQuery plugin on the web tells you to use document.ready, lots of people are just going to copy and paste that, I wanted to know if it'd still behave as usual as part of the <body>

Thanks, interesting smile


#19

This is starting to change in some of the very latest browsers smile
http://www.stevesouders.com/blog/2010/02/07/browser-script-loading-roundup/


#20

No, I didn't say you were stupid for asking the question. I only wondered why you'd want to do something as stupid as using an event handler for something that was already at the end of the document.

Is it really that much work to rewrite $(document).ready(myFunction); as myFunction();? You must lead a very stressful life, Dan! smiley