Как вставить JavaScript код в веб-страницу

Раздел: Веб-разработка -> Встраивание скриптов

Основные подходы к подключению скриптов в HTML

Как подключить внешний JavaScript файл стандартным способом?

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

<!DOCTYPE html>
<html lang="ru">
<head>
  <meta charset="UTF-8">
  <title>Пример</title>
</head>
<body>
  <h1>Заголовок</h1>
  <script src="js/script.js"></script>
</body>
</html>

Link js html (подключение javascript файла к html)

Пояснение: файл script.js должен находиться в папке js относительно HTML-документа. Скрипт выполняется после парсинга всего содержимого <body>, поэтому элементы страницы уже будут существовать.

Типичная ошибка: неправильный путь к файлу. Например, если файл лежит в корне, а в атрибуте указан путь js/script.js, браузер вернёт 404. Решение: проверять расположение файла относительно HTML или использовать абсолютный путь (начинающийся с /).

Проблема блокировки рендеринга: если скрипт размещён в <head>, он задерживает отображение страницы до полной загрузки и выполнения. Лучше размещать скрипты перед закрывающим </body> или использовать атрибуты async/defer.

Цель использования: подключение больших или часто обновляемых скриптов, которые целесообразно хранить отдельно от HTML.

Как встроить JavaScript код непосредственно в HTML-документ?

Код можно разместить внутри тега <script> без атрибута src. Это удобно для небольших скриптов (аналитика, микро-анимации) или когда нужно быстро протестировать логику. Однако такой подход усложняет поддержку и переиспользование кода.

<script>
  document.querySelector('h1').style.color = 'blue';
</script>

Пояснение: скрипт выполняется сразу при парсинге, поэтому важно, чтобы элемент h1 уже был объявлен выше в коде. Иначе получим ошибку TypeError: Cannot read properties of null.

Типичная ошибка: попытка обратиться к элементу, который ещё не загружен. Решение: размещать inline-скрипт после элементов, с которыми он работает, или оборачивать в DOMContentLoaded.

Недостаток: смешивание структуры и поведения, что затрудняет чтение кода и его кэширование браузером.

Цель использования: быстрая вставка одноразового кода (например, для отправки формы без внешних зависимостей).

Как загрузить скрипт асинхронно с помощью атрибута async?

Атрибут async позволяет браузеру загружать скрипт параллельно с парсингом HTML и выполнять его сразу после загрузки, не дожидаясь завершения парсинга. Подходит для независимых скриптов (например, рекламных баннеров, счётчиков), которые не требуют определённого порядка выполнения.

<script async src="js/analytics.js"></script>

Пояснение: браузер продолжает парсить HTML, пока загружается analytics.js. Как только файл загрузится, выполнение скрипта приостанавливает парсинг до завершения.

Типичная ошибка: использование async для скриптов, которые зависят от другого скрипта или от DOM. В этом случае порядок выполнения не гарантируется, что может привести к ошибкам.

Решение: если скрипты зависимы, лучше использовать defer или вручную управлять очередностью через события загрузки.

Цель использования: загрузка сторонних виджетов, аналитики или других скриптов, не влияющих на отображение страницы.

Как отложить выполнение скрипта до полного парсинга HTML с помощью атрибута defer?

Атрибут defer загружает скрипт асинхронно (параллельно с парсингом), но откладывает его выполнение до тех пор, пока весь HTML не будет полностью разобран. Это гарантирует, что скрипт увидит готовое DOM-дерево и выполнится в порядке следования в документе.

<script defer src="js/dom-manipulation.js"></script>

Пояснение: скрипт начнёт загружаться сразу, но выполнится только после того, как браузер закончит парсинг HTML. При этом скрипты с defer выполняются последовательно.

Типичная ошибка: применение defer к inline-скриптам (без src) - атрибут игнорируется. Для inline-кода нужно использовать другие методы (например, DOMContentLoaded).

Решение: всегда использовать defer только для внешних файлов с атрибутом src.

Цель использования: скрипты, которые манипулируют DOM, но не должны блокировать загрузку страницы (например, слайдеры, меню).

Как использовать модули ES (type="module") для подключения скриптов?

Атрибут type="module" позволяет использовать синтаксис import/export внутри скрипта. Такие скрипты по умолчанию ведут себя как с defer: загружаются асинхронно и выполняются после парсинга. Подходит для современных приложений с модульной архитектурой.

<script type="module" src="js/app.js"></script>

Пояснение: внутри app.js можно импортировать другие модули. Браузер загружает все зависимости и выполняет код только после того, как DOM готов.

Типичная ошибка: использование модулей с файловой системы (протокол file://) приводит к ошибкам CORS. Решение: запускать проект через локальный веб-сервер (например, Live Server в VS Code) или использовать http://.

Проблема совместимости: старые браузеры не поддерживают type="module". Для них необходимо предусмотреть fallback (полифиллы или сборщик).

Цель использования: разработка SPA, использование npm-пакетов в браузере без сборщиков (для небольших проектов).

Как динамически загрузить JavaScript-файл через создание элемента script?

С помощью document.createElement('script') можно добавить скрипт на страницу в любой момент, например, после нажатия кнопки. Это полезно для загрузки тяжёлых библиотек по требованию.

const script = document.createElement('script');
script.src = 'js/chart.js';
script.onload = function() {
  console.log('Скрипт загружен');
  // Инициализация библиотеки
};
document.body.appendChild(script);

Пояснение: скрипт загружается асинхронно (как с async). После успешной загрузки вызывается обработчик onload, в котором можно безопасно использовать функциональность библиотеки.

Типичная ошибка: забыть добавить скрипт в DOM - без вызова appendChild загрузка не начнётся.

Проблема: если скрипт загружается с ошибкой, onerror не срабатывает по умолчанию. Решение: добавить обработчик script.onerror для логирования.

Цель использования: ленивая загрузка тяжёлых скриптов (например, редактора текста, 3D-движков) для ускорения начальной загрузки страницы.

Как выполнить скрипт после полной загрузки страницы (всех ресурсов)?

Событие window.onload (или window.addEventListener('load', ...)) срабатывает после загрузки всех изображений, стилей и фреймов. Это гарантирует, что любой внешний ресурс уже доступен. Может использоваться для скриптов, которым нужны размеры изображений или данные из iframe.

<script>
  window.addEventListener('load', function() {
    console.log('Все ресурсы загружены');
  });
</script>

Пояснение: код внутри обработчика выполняется только после полной загрузки страницы, включая все асинхронные ресурсы.

Типичная ошибка: путаница с DOMContentLoaded. Последний срабатывает, когда DOM готов, но внешние ресурсы (изображения) могут ещё загружаться. Если скрипту нужны именно размеры изображений, следует использовать load.

Недостаток: ожидание всех ресурсов может замедлить выполнение, особенно если на странице много тяжёлых изображений.

Цель использования: скрипты, которые полагаются на загруженные медиа-файлы (например, галереи с предзагрузкой).

Расширенные примеры подключения скриптов

Пример
<!-- Пример 1: Сравнение async и defer -->
<!DOCTYPE html>
<html lang="ru">
<head>
  <meta charset="UTF-8">
  <title>Async vs Defer</title>
  <script async src="https://example.com/async.js"></script>
  <script defer src="https://example.com/defer.js"></script>
</head>
<body>
  <div id="output"></div>
  <script>
    document.getElementById('output').textContent = 'Парсинг HTML завершён';
  </script>
</body>
</html>

/* Результат: порядок вывода в консоль может быть:
   - если async.js загрузится быстро: 'async.js выполнен' (до 'Парсинг HTML завершён')
   - defer.js всегда выполняется после парсинга HTML, но до скрипта в body? Нет, defer выполняется после парсинга, но перед скриптами без defer? Важный нюанс: скрипты без defer/async выполняются синхронно, поэтому скрипт в body выполнится раньше, чем defer (так как defer отложен до парсинга, а синхронный выполняется сразу). Если убрать скрипт в body, defer выполнится после завершения парсинга.
   В данном примере порядок: парсинг HTML -> выполнение синхронного скрипта -> выполнение defer (если async уже загрузился, он мог выполниться раньше).
   Но для демонстрации лучше использовать консоль. */
(Консоль браузера)
"async.js выполнен"   (может быть раньше или позже)
"Парсинг HTML завершён"
"defer.js выполнен"
Пример
<!-- Пример 2: Динамическая загрузка скрипта с обработкой ошибок -->
<script>
function loadScript(url, callback) {
  const script = document.createElement('script');
  script.src = url;
  script.onload = () => {
    console.log(url + ' загружен');
    if (callback) callback();
  };
  script.onerror = () => {
    console.error('Ошибка загрузки ' + url);
    // Можно попробовать альтернативный URL
  };
  document.head.appendChild(script);
}

loadScript('https://cdn.jsdelivr.net/npm/lodash@4.17.21/lodash.min.js', () => {
  console.log('Lodash доступен:', typeof _ !== 'undefined');
});
</script>
(Консоль)
"https://cdn.jsdelivr.net/npm/lodash@4.17.21/lodash.min.js загружен"
"Lodash доступен: true"
Пример
<!-- Пример 3: Модуль ES с импортом -->
<!-- index.html -->
<!DOCTYPE html>
<html lang="ru">
<head>
  <meta charset="UTF-8">
  <title>Модуль ES</title>
</head>
<body>
  <p id="greeting"></p>
  <script type="module">
    import { sayHello } from './utils.js';
    document.getElementById('greeting').textContent = sayHello('Мир');
  </script>
</body>
</html>

<!-- utils.js -->
export function sayHello(name) {
  return `Привет, ${name}!`;
}
Страница отобразит: "Привет, Мир!"
Пример
<!-- Пример 4: Ошибка пути к скрипту и её исправление -->
<!-- Неверный путь -->
<script src="scripts/app.js"></script>
<!-- В консоли: GET http://example.com/scripts/app.js 404 (Not Found) -->

<!-- Правильный вариант, если скрипт лежит в той же папке -->
<script src="app.js"></script>
<!-- Или использовать абсолютный путь от корня: -->
<script src="/js/app.js"></script>
<!-- Если используется локальный сервер, путь должен быть относительно корня сервера -->
При неверном пути в консоли будет ошибка 404, скрипт не выполнится.

Подключение JavaScript файла к HTML - comments

En
Link js html (javascript)