# External scripts If we have a lot of JavaScript code, we can it put it into a separate file. The script file is attached to HTML like this: ```html ``` Here `/path/to/script.js` is an absolute path to the file with the script (from the site root). It is also possible to provide a path relative to the current page. For instance, `src="script.js"` would mean a file `"script.js"` from the current folder. We can give a full URL al well, for instance: ```html ``` To attach several scripts, use multiple tags: ```html … ``` [smart] As a rule, only simplest scripts are put into HTML. More complex ones reside in separate files. The benefit of a separate file is that the browser will download it and then store in its [cache](https://en.wikipedia.org/wiki/Web_cache). After it, other pages which want the same script will take it from the cache instead of downloading it. So the file is actually downloaded only once. That saves traffic and makes pages faster. [/smart] [warn header="If `src` is set, the script content is ignored."] A single ` ``` We must choose: either it's an external ` ``` [/warn] ## Asynchronous scripts: defer/async Browser loads and shows HTML gradually as it comes. That's clearly noticeable on the slow internet connection. The browser doesn't wait for the page to load fully. It shows the part that has been loaded already, and then adds content to it as it loads. As we noted before, when the browser meets a ` */!*

Rabbits counted!

``` The behavior is called "synchronous". Usually it causes no problems, but there's an important consequence. **If the script is external, then until the browser executes it, it can't show the page below.** So, in this document, until `big.js` loads and executes, the `` content is hidden: ```html *!* */!* This text is not shown until the browser executes big.js. ``` The question is -- do we really want to hide the body until the script finishes? Most of time, we don't. Sometimes, a script may contain a very important code that really must be loaded before the rest of the page is parsed (and the scripts below executed). But that's an exception. Usually it's ok that a visitor can see the page content while the script is loading. [warn header="Blocking is dangerous"] There are situations when such blocking is even dangerous. Let's say we attach a script from the banner system, or a 3rd-party integration code. Like this: ```html Information below is not shown until the script loads and executes.

…Important information!

``` It's just wrong that the rest of the page is not shown until the banner is loaded. The banner is not that important. And what if their server is overloaded and responds slowly? Our visitors will wait even more. Here's an example of such "slow" script (the delay is artificial here): ```html Wait. The text belown will shown up only after the script executes.

…Important information!

``` [/warn] So, how to "fix" the blocking behavior? Our first attempt could be to put all such scripts to the bottom of the ``, after all content. Then the browser will show the content first and then load the script. Problem gone. But the solution is not perfect:
  1. The script won't start loading until the whole page loads. If the page is large, then the delay may be significant. We'd like the browser to start loading a script early, but still do not block the page.
  2. If there is more than one script at the bottom of the page, and the first script is slow, then the second one will have to wait for it. Browser executes only one `

    …Important information!

    ``` Now if we run it, we'll see that the whole document is displayed immediately, and the external script runs when it loads. ## Defer vs Async: order Let's discuss these differences in more detail. For example, in the code below (with `async`) there are two scripts. The one which loads first will run first. ```html ``` If `2.js` is bigger than `1.js`, it may happen that `2.js` will run before `1.js`. That's normal. Async scripts are totally independent. And in the code below `defer` is used, which forces browser to keeps execution order. Even if `2.js` loads first, it waits and executes after `1.js`: ```html ``` This feature of "deferred" scripts is important when `2.js` relies on the result of `1.js` and we must be sure that the order is determined. ## Defer vs Async: page A script with `defer` always works when the HTML-document is fully processed by the browser. That feature comes into play when the document is large, like: ```html Too long text. Didn't read. Many words. ... ``` ...Here `async.js` executes when it loads -- possibly, before the document is fully loaded. In contrast, `defer.js` always waits for the full document to be ready. The choice between `defer` and `async` here depends on our intentions. Sometimes a script doesn't need the document at all (like a counter), it should execute ASAP. In this case `async` is superb. And in another case a script may need the whole document to do some work with it. Then `defer` is preferable. ## Summary Before inserting an external `