32

In todays modern age, where lots of (popular) javascripts files are loaded externally and locally, does the order in which the javascripts files are called matter especially when all local files are all combined (minified) into one file?

Furthermore, many claim that Javascript should go in the bottom of the page while others say javascript is best left in the head. Which should one do when? Thanks!


google cdn latest jquery js              | external
another cdn loaded javascript js         | external

TabScript  ...js          \
GalleryLightbox  ...js     \
JavascriptMenu  ...js       \
HTMlFormsBeautifier ...js    > all minified and combined into one .js file!
TextFieldResize  ...js      /
SWFObjects  ...js          /
Tooltips ...js            /
CallFunctions   ...js    /

Sam
  • 15,254
  • 25
  • 90
  • 145
  • 4
    In my experience, JavaScript placed in the head is more maintainable. The ordering that the scripts are loaded in seems to matter less. I have read that JS in the body is faster. I'll give you that :) But if I can't guarantee uptime to my clients, then the extra milliseconds are worthless. If developers spend more time worrying if a change they made will break the JavaScript due to dependencies and less on the real business problems, then progress is much slower. With that said, I don't think there is a right or wrong answer, but my personal preference is that JS goes in the head – jamesmortensen Feb 14 '11 at 01:30

5 Answers5

30

Order matters in possibly one or more of the following situations:

  • When one of your scripts contains dependencies on another script.
  • If the script is in the BODY and not the HEAD.. UPDATE: HEAD vs BODY doesn't seem to make a difference. Order matters. Period.
  • When you are running code in the global namespace that requires a dependency on another script.

The best way to avoid these problems is to make sure that code in the global namespace is inside of a $(document).ready() wrapper. Code in the global namespace must be loaded in the order such that executed code must first be defined.

Checking the JavaScript error console in Firebug or Chrome Debugger can possibly tell you what is breaking in the script and let you know what needs to be modified for your new setup.

Order generally doesn't matter if functions are invoked based on events, such as pageload, clicks, nodes inserted or removed, etc. But if function calls are made outside of the events in the global namespace, that is when problems will arise. Consider this code:

JS file: mySourceContainingEvilFunctionDef.js

function evilGlobalFunctionCall() {
    alert("I will cause problems because the HTML page is trying to call " +
      "me before it knows I exist...  It doesn't know I exist, sniff :(  ");
}

HTML:

    <script>
        evilGlobalFunctionCall();  // JS Error - syntax error 
    </script>
    <!-- Takes time to load -->
    <script type="text/javascript" src="mySourceContainingEvilFunctionDef.js"></script>
...

In any case, the above tips will help prevent these types of issues.


As a side note, you may want to consider that there are certain speed advantages to utilizing the asynchronous nature of the browser to pull down resources. Web browsers can have up to 4 asynchronous connections open at a time, meaning that it's quite possible that your one massive script might take longer to load than that same script split up into chunks! There is also Yahoo Research that shows combining scripts produces the faster result, so results vary from one situation to another.

Since it's a balance between the time taken to open and close several HTTP connections vs the time lost in limiting yourself to a single connection instead of multiple asynchronous connections, you may need to do some testing on your end to verify what works best in your situation. It may be that the time taken to open all of the connections is offset by the fact that the browser can download all the scripts asynchronously and exceed the delays in opening/closing connections.

With that said, in most cases, combining the script will likely result in the fastest speed gains and is considered a best practice.

jamesmortensen
  • 33,636
  • 11
  • 99
  • 120
  • Each spawned HTTP request also adds the latency of sending the request and waiting for the response, aside from downloading the actual file. It's generally considered best practice to combine all of your JavaScript into one document to avoid multiple unnecessary HTTP requests. – Andrew Noyes Feb 14 '11 at 01:07
  • @Andrew - Yes, I pointed that out in my answer. But it's also true that results may vary, and the same documentation that suggests combining scripts also suggests that it may be faster to split content across multiple domains to take advantage of the asynchronous nature of the browser and the 4 connection limit. It's really up to each team to determine which is faster for their given situation. Since combining is considered best practice, chances are that will be better, but I don't believe it's guaranteed. – jamesmortensen Feb 14 '11 at 01:13
  • @jmort *The best way to avoid these problems is to just load the code up in the HEAD section to ensure that all of the JavaScript code is loaded before it's run* Could you elaborate on this? What is the advantage of putting the SCIRPT elements in the HEAD as compared to putting them in the BODY? – Šime Vidas Feb 14 '11 at 01:29
  • @jmort Also, you are saying that order does matter for SCRIPT elements in the BODY, but does not matter for SCRIPT elements in the HEAD, right? – Šime Vidas Feb 14 '11 at 01:30
  • If I put JS in the body, those scripts run as soon as loading is complete, which means that order matters. But in the head, I can do crazy things like put the JQuery validator JS `above` the JQuery core script imports and it doesn't matter. In the body, the Validator code would load up and try to run and then complain that $ is a syntax error. – jamesmortensen Feb 14 '11 at 01:33
  • @Sime - I just tried an example with JQuery Validator and JQuery. I reversed the order of the scripts in the HEAD, and it seems that **I have been proven wrong.** Because JQuery Validator is wrapped in an anonymous function, it executes immediately, prior to the JQuery Core library loading. Thus, it seems that order matters everywhere in cases where functions are called in the global namespace. This will give me quite a bit to think about for awhile. Thanks for pointing that out. – jamesmortensen Feb 14 '11 at 01:42
  • @jmort My testing does not back up your claims. See here: http://vidasp.net/tinydemos/dependencies/ There are two files in that directory. In one file 2 scripts are loaded in the head, in the other file those 2 scripts are loaded in the body. The first script is jQuery. The second one is jQuery templates (which depends on jQuery). In **both** cases I get an error ( Uncaught ReferenceError: jQuery is not defined ) – Šime Vidas Feb 14 '11 at 01:44
  • @Sime - I just ran the same tests myself, and I have updated my answer to remove the incorrect information. Thanks for trying that on your end too. – jamesmortensen Feb 14 '11 at 01:47
  • @jmort The problem with placing SCRIPT elements in the HEAD is that loading external JS files may cause an delay in loading of other resources (like images). You can see in this example ( http://vidasp.net/tinydemos/why-you-should-put-your-scripts-at-the-bottom.jpg ) that placing 2 scripts in the HEAD delayed the loading of images by **2 seconds** which is a pretty serious issue. – Šime Vidas Feb 14 '11 at 01:51
  • After reading through the comments and answers, I would like to add `defer` and `type=module` as better way to ensure ordered execution of scripts. This all together eliminates the question of positioning the JS in HTML and their dependencies, even though, if you prefer your JS internal for some reason. – odus-ex May 01 '22 at 10:22
8

Yes, depending very much on what you do.

For example, if a.js had...

var a = function() {
   alert('a');
}

...and b.js had...

a()

...then you wouldn't want to include b.js before a.js, or a() won't be available.

This only applies to function expressions; declarations are hoisted to the top of their scope.

As for whether you should combine jQuery, I reckon it would be better to use the Google hosted copy - adding it to your combined file will make it larger when there is a great chance the file is already cached for the client.

alex
  • 479,566
  • 201
  • 878
  • 984
4

Read this post from the webkit team for some valuable information about how browsers load and execute script files.

Normally when the parser encounters an external script, parsing is paused, a request is issued to download the script, and parsing is resumed only after the script has fully downloaded and executed.

So normally (without those async or defer attributes), scripts get excuted in the order in which they are specified in the source code. But if the script tags are in the <head>, the browser will first wait for all scripts to load before it starts executing anything.

This means that it makes no difference if the script is splitted into multiple files or not.

Jannes Meyer
  • 1,228
  • 1
  • 9
  • 18
1

If I'm understanding your question I think you're asking if it matters where in a file a function/method is defined, and the answer is no, you can define them anywhere in a single source file. The JavaScript parser will read in all symbols before trying to run the code.

Andrew Noyes
  • 5,248
  • 1
  • 18
  • 14
1

If you have two files that define variables or functions with the same name, the order that they're included will change which one actually is defined