Тег script в HTML: как подключить JavaScript

Тег <script> подключает к странице JavaScript - код, который меняет разметку, реагирует на действия посетителя и обращается к серверу без перезагрузки страницы. Код можно прописать прямо между тегами <script> и </script>, а можно вынести в отдельный файл и подключить через атрибут src - тем же принципом, каким <link> подключает внешний файл CSS. <script> можно прописать и в <head>, и в body, и не один раз на странице - но от места и атрибутов зависит, когда именно браузер его выполнит.

HTML
<script src="app.js"></script>
 
<script>
  console.log('код прямо в HTML');
</script>
 
<script type="module" src="app.mjs"></script>

Код между тегами или файл через src

У <script>, в отличие от <link>, есть два равноправных способа задать код - через атрибут src или прямо между открывающим и закрывающим тегом. Но если указать оба способа сразу, браузер не выполнит оба - он скачает и выполнит только внешний файл из src, а всё, что написано между тегами, просто проигнорирует.

HTML
<script src="app.js">
  console.log('этот код браузер не выполнит');
</script>

Пример: что выполнится на самом деле

Включите или выключите src и нажмите на кнопку - ниже настоящий результат выполнения тега с текущими настройками:

Результат

Это настоящее выполнение тега <script> браузером, а не имитация: при включённом src реально скачивается и выполняется отдельный файл (в примере - через data-адрес вместо обычного пути), а код между тегами реально остаётся без внимания.

async и defer: когда выполняется скрипт

Без дополнительных атрибутов обычный <script src="..."> останавливает разбор HTML на своём месте: браузер сначала полностью скачивает и выполняет файл и только потом читает страницу дальше. Для страницы с несколькими скриптами это заметно замедляет отображение, поэтому у <script> есть два атрибута, которые убирают эту остановку - но по-разному.

HTML
<script src="app.js"></script>
<script src="app.js" async></script>
<script src="app.js" defer></script>

Оба атрибута требуют src и не работают на коде между тегами. Разница между ними - в том, что происходит, как только файл скачался: async выполняет его сразу же, прерывая разбор HTML на короткий момент, а порядок нескольких async-скриптов относительно друг друга не гарантирован. defer ничего не прерывает - откладывает выполнение до конца разбора всего HTML и выполняет скрипты строго по порядку, в котором они стоят на странице. Отсюда и практическое правило: если скрипту важен порядок или доступ к уже построенной разметке - нужен defer, а если скрипт независимый от остальных, вроде счётчика или виджета, - подойдёт async.

Пример: три схемы загрузки

Выберите атрибут - ниже условная временная шкала (не точный хронометраж в секундах, а соотношение событий):

Результат
Разбор HTMLразборСТОПразбор
Скриптзагрузка + выполнение

Остальные атрибуты: type module, integrity, nonce

АтрибутДля чего
type="module"Подключает ES-модуль - код с import/export. Модули всегда откладываются как с defer, даже без этого атрибута явно
blocking="render"Просит задержать первую отрисовку страницы до этого скрипта. Нужен только скриптам, добавленным через JS - те, что браузер находит при обычном разборе head, и так блокируют отрисовку по умолчанию
integrityХэш файла для проверки, что подключаемый по src скрипт не подменили на сервере или CDN. По спецификации не используется без src
nonceОдноразовый код, который разрешает выполнение именно этого скрипта при включённой политике безопасности CSP (Content-Security-Policy)
crossoriginРазрешает браузеру показать подробности ошибки во внешнем скрипте с другого домена, а не общее «Script error»

Как делать не надо при работе с тегом script

С <script> ошибки почти всегда связаны не с назначением тега, а с порядком его выполнения или с синтаксисом вокруг src:

ОшибкаЧто происходитКак исправить
Указаны и src, и код между тегамиБраузер выполняет только внешний файл из src, код между тегами полностью игнорируется (см. пример выше)Выбрать что-то одно - либо src, либо код между тегами
Скрипт с обращением к элементам страницы находится в head без async/deferЭлементы, к которым обращается код (например через getElementById), ещё не существуют в момент выполнения - скрипт падает с ошибкой или просто не находит ихИспользовать defer, либо переносить обычный <script> в конец body, после нужной разметки
javascript: в href ссылки вместо обработчика событияСсылка формально работает, но ломает доступность - не работает открытие в новой вкладке, не виден статус ссылки, хуже работает со скринридерамиОбычный href на реальный адрес, а клик обрабатывать через addEventListener или атрибут onclick
Самозакрывающийся <script src="..." />В HTML (в отличие от XML) самозакрытие для script не поддерживается - браузер продолжает ждать отдельный закрывающий тег и может утащить в «тело» скрипта часть страницы дальшеВсегда закрывать явным </script>, даже при пустом содержимом и наличии src
integrity указан без srcАтрибут проверяет файл, который скачивается по адресу из src - без него проверять нечего, указание бессмысленноИспользовать integrity только вместе с src на внешний файл
Категория
Поделиться в социальных сетях

Отправить комментарий

0 Комментарии

Отправить комментарий (0)

#buttons=(Хорошо) #days=(20)

Мы используем файлы cookie для улучшения работы сайта. Подробнее
Хорошо
×