# Внешние скрипты, порядок исполнения Если JavaScript-кода много -- его выносят в отдельный файл, который подключается в HTML: ```html ``` Здесь `/path/to/script.js` -- это абсолютный путь к файлу, содержащему скрипт (из корня сайта). Браузер сам скачает скрипт и выполнит. Можно указать и полный URL, например: ```html ``` Вы также можете использовать путь относительно текущей страницы, например `src="lodash.js"` обозначает файл из текущей директории. Чтобы подключить несколько скриптов, используйте несколько тегов: ```html ... ``` [smart] Как правило, в HTML пишут только самые простые скрипты, а сложные выносят в отдельный файл. Браузер скачает его только первый раз и в дальнейшем, при правильной настройке сервера, будет брать из своего [кеша](http://ru.wikipedia.org/wiki/%D0%9A%D1%8D%D1%88). Благодаря этому один и тот же большой скрипт, содержащий, к примеру, библиотеку функций, может использоваться на разных страницах без полной перезагрузки с сервера. [/smart] [warn header="Если указан атрибут `src`, то содержимое тега игнорируется."] В одном теге `SCRIPT` нельзя одновременно подключить внешний скрипт и указать код. Вот так не cработает: ```html ``` Нужно выбрать: либо `SCRIPT` идёт с `src`, либо содержит код. Тег выше следует разбить на два: один -- с `src`, другой -- с кодом, вот так: ```html ``` [/warn] ## Асинхронные скрипты: defer/async Браузер загружает и отображает HTML постепенно. Особенно это заметно при медленном интернет-соединении: браузер не ждёт, пока страница загрузится целиком, а показывает ту часть, которую успел загрузить. Если браузер видит тег ` */!*

Кролики посчитаны!

``` Такое поведение называют "синхронным". Как правило, оно вполне нормально, но есть важное следствие. **Если скрипт -- внешний, то пока браузер не выполнит его, он не покажет часть страницы под ним.** То есть, в таком документе, пока не загрузится и не выполнится `big.js`, содержимое `` будет скрыто: ```html *!* */!* Этот текст не будет показан, пока браузер не выполнит big.js. ``` И здесь вопрос -- действительно ли мы этого хотим? То есть, действительно ли оставшуюся часть страницы нельзя показывать до загрузки скрипта? Есть ситуации, когда мы не только НЕ хотим такой задержки, но она даже опасна. Например, если мы подключаем внешний скрипт, который показывает рекламу или вставляет счётчик посещений, а затем идёт наша страница. Конечно, неправильно, что пока счётчик или реклама не подгрузятся -- оставшаяся часть страницы не показывается. Счётчик посещений не должен никак задерживать отображение страницы сайта. Реклама тоже не должна тормозить сайт и нарушать его функционал. А что, если сервер, с которого загружается внешний скрипт, перегружен? Посетитель в этом случае может ждать очень долго! Вот пример, с подобным скриптом (стоит искусственная задержка загрузки): ```html

Важная информация не покажется, пока не загрузится скрипт.

...Важная информация!

``` Что делать? Можно поставить все подобные скрипты в конец страницы -- это уменьшит проблему, но не избавит от неё полностью, если скриптов несколько. Допустим, в конце страницы 3 скрипта, и первый из них тормозит -- получается, другие два его будут ждать -- тоже нехорошо. Кроме того, браузер дойдёт до скриптов, расположенных в конце страницы, начнут грузиться только тогда, когда вся страница загрузится. А это не всегда правильно, например счётчик посещений наиболее точно сработает, если загрузить его пораньше. Поэтому "расположить скрипты внизу" -- не лучший выход. Кардинально решить эту проблему помогут атрибуты `async` или `defer`:
Атрибут `async`
Поддерживается всеми браузерами, кроме IE9-. Скрипт выполняется полностью асинхронно. То есть, при обнаружении ` ``` А в таком коде (с `defer`) первым сработает всегда `1.js`, а скрипт `2.js`, даже если загрузился раньше, будет его ждать. ```html ``` Поэтому атрибут `defer` используют в тех случаях, когда второй скрипт `2.js` зависит от первого `1.js`, к примеру -- использует что-то, описанное первым скриптом. Второе отличие -- скрипт с `defer` сработает, когда весь HTML-документ будет обработан браузером. Например, если документ достаточно большой... ```html Много много много букв ``` ...То скрипт `async.js` выполнится, как только загрузится -- возможно, до того, как ведь документ готов. А `defer.js` подождёт готовности всего документа. Это бывает удобно, когда мы в скрипте хотим работать с документом, и должны быть уверены, что он полностью получен.
[warn header="Либо `async` либо `defer`"] Одновременно указывать `async` и `defer` не имеет смысла, в этом случае браузер использует только `async`. [/warn] [warn header="Атрибуты `async/defer` -- только для внешних скриптов"] Атрибуты `async/defer` работают только в том случае, если назначены на внешние скрипты, т.е. имеющие `src`. При попытке назначить их на обычные скрипты <script>...</script>, они будут проигнороированы. [/warn] Тот же пример с `async`: ```html

Важная информация теперь не ждёт, пока загрузится скрипт...

...Важная информация!

``` При запуске вы увидите, что вся страница отобразилась тут же, а `alert` из внешнего скрипта появится позже, когда загрузится скрипт. [smart header="Эти атрибуты давно \"в ходу\""] Большинство современных системы рекламы и счётчиков знают про эти атрибуты и используют их. Перед вставкой внешнего тега ``
  • Специальные атрибуты `async` и `defer` используются для того, чтобы пока грузится внешний скрипт -- браузер показал остальную (следующую за ним) часть страницы. Без них этого не происходит.
  • Разница между `async` и `defer`: атрибут `defer` сохраняет относительную последовательность скриптов, а `async` -- нет. Кроме того, `defer` всегда ждёт, пока весь HTML-документ будет готов, а `async` -- нет.
  • Очень важно не только читать учебник, но делать что-то самостоятельно. Решите задачки, чтобы удостовериться, что вы все правильно поняли.