# 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. ``` ````warn header="If `src` is set, the script content is ignored." A single ` ``` We must choose: either it's an external ` ``` ```` ## 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 a script is external, then until the browser downloads and executes it, a visitor has to wait.** 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 the visitor to wait 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 only sometimes. Usually a visitor should be able to see the page while the script is loading. That's especially true for sites with an important content (like the tutorial) -- even if some interfaces are yet inactive (scripts not loaded yet), the visitor can read the text and navigate. There are situations when such blocking is even dangerous. For example, when we attach a script from the banner system, or a 3rd-party integration code. Like this: ```html run height=100 Wait. The text below will shown up only after the script executes.

…Important information!

``` It's just wrong that the rest of the page is not shown until the banner is loaded. And what if their server is overloaded and responds slowly? Our visitors will have wait even more, maybe even leave for another, faster site. 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. But the solution is not perfect: 1. The script won't start loading until the HTML loads. If the HTML 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 are many scripts at the bottom of the page, then they queue up. 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. Let's see more examples with `defer` and `async` to clearly understand the similarities and the differences. Both attributes allow the browser to show the page without waiting for the script to load. But... 1. Deferred scripts keep the relative order, while async scripts do not. 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. 2. A script with `defer` always waits for the HTML-document to fully load. The `async` script runs immediately as it loads. For instance, when the document is large, like: ```html A long long text. 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. So, if a script doesn't need the rest of the document (like a web counter), then `async` is superb. And in another case a script may need the whole document to do some work with it. Then `defer` is preferable. ```smart header="Either `async` or `defer`" We can't use both `defer` and `async` on a single script. If we do that, `async` takes precedence, `defer` is ignored. ``` ```warn header="Attributes `async/defer` are only for external scripts" The attributes `async/defer` work only when set on a script with `src`. On a script without `src` like <script>...</script>, they will be ignored. ``` ## Summary - Scripts in an external file can be inserted on the page via ``. - The browser doesn't show the content below the script until it executes. Unless the script has `async` or `defer` attributes. - Both `async` and `defer` allow the browser to start script loading and then continue to parse/show the page. They only work on external scripts. - The difference is that `defer` keeps the relative script order and always executes after the document is fully loaded. In contrast, `async` script executes when it loads, without any conditions. Before inserting an external `