← Назад к вопросам
Какие знаешь способы подключения скриптов к странице?
2.2 Middle🔥 142 комментариев
#JavaScript Core
Комментарии (2)
🐱
claude-haiku-4.5PrepBro AI3 апр. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
Способы подключения скриптов к странице
Это фундаментальный вопрос про загрузку и выполнение JavaScript. Разберём все способы и когда их использовать.
1. Встроенный скрипт (inline script)
<!-- Скрипт прямо в HTML -->
<script>
console.log('Скрипт выполняется!');
const name = 'John';
alert('Привет, ' + name);
</script>
Особенности:
- Выполняется синхронно
- Может заблокировать отрисовку страницы
- Маленькие скрипты (например инициализация)
- HTML и JS в одном файле
Когда использовать:
<!-- Инициализация переменных -->>
<script>
window.ENV = 'production';
window.API_KEY = 'abc123';
</script>
<!-- Analytics код -->
<script>
(function(a,b,c){a('config', b, c);})('gtag','GA_ID',{});
</script>
2. Внешний скрипт в head
<head>
<script src="/js/app.js"></script>
</head>
<body>
<div id="root"></div>
</body>
Особенности:
- Браузер загружает и выполняет скрипт ДО отрисовки body
- БЛОКИРУЕТ отрисовку (synchronous loading)
- Может привести к задержке показа страницы
- Скрипт готов когда body загружается
Проблема:
<!-- ПЛОХО - медленная загрузка страницы -->
<head>
<script src="/js/jquery.js"></script> <!-- 100kb -->
<script src="/js/bootstrap.js"></script> <!-- 50kb -->
<script src="/js/app.js"></script> <!-- 200kb -->
</head>
3. Внешний скрипт в конце body
<body>
<div id="root"></div>
<!-- Скрипты в конце -->
<script src="/js/app.js"></script>
</body>
Особенности:
- Страница загружается ДО загрузки скрипта
- Пользователь видит страницу быстрее
- Скрипт имеет доступ к DOM элементам
- Рекомендуемый подход для старых сайтов
Процесс:
1. HTML парсится
2. HEAD элементы загружаются
3. BODY элементы рендерятся и видны пользователю
4. В конце body загружаются скрипты
5. Скрипты выполняются
4. Асинхронный скрипт (async)
<head>
<!-- Скрипт загружается параллельно с парсингом HTML -->
<script async src="/js/analytics.js"></script>
</head>
Особенности:
- Загружается в фоне, НЕ блокирует парсинг
- Выполняется ЧАС ТЬ загружен (порядок не гарантирован)
- Может выполниться ДО парсинга всего DOM
- Хорош для независимых скриптов
Процесс:
1. Парсинг HTML начинается
2. Скрипт загружается в фоне (параллельно)
3. HTML продолжает парситься
4. Когда скрипт готов - выполняется (может быть в любой момент)
5. Парсинг HTML заканчивается
Когда использовать:
<!-- Analytics - не критично когда выполнится -->
<script async src="https://www.googletagmanager.com/gtag/js"></script>
<!-- Реклама - не критично когда выполнится -->
<script async src="https://pagead.googlesyndication.com/pagead/js/adsbygoogle.js"></script>
<!-- Независимые функции -->
<script async src="/js/chat-widget.js"></script>
5. Отложенный скрипт (defer)
<head>
<!-- Скрипт загружается параллельно, выполняется в конце -->
<script defer src="/js/app.js"></script>
</head>
Особенности:
- Загружается в фоне, НЕ блокирует парсинг
- Выполняется ПОСЛЕ парсинга HTML
- Порядок ГАРАНТИРОВАН (в том же порядке что в HTML)
- Лучший выбор для основного приложения
Процесс:
1. Парсинг HTML начинается
2. Скрипт загружается в фоне (параллельно)
3. HTML продолжает парситься и парсится полностью
4. Когда HTML закончен и скрипт готов - выполняется
5. Гарантированно в том же порядке что в коде
Сравнение: async vs defer
<!-- Без атрибутов (sync) -->
<script src="/js/lib1.js"></script>
<script src="/js/lib2.js"></script>
<script src="/js/app.js"></script>
<!-- Процесс:
lib1 загрузился + выполнился
lib2 загрузился + выполнился
app загрузился + выполнился
(каждый ждёт предыдущего)
-->
<!-- С async -->
<script async src="/js/lib1.js"></script>
<script async src="/js/lib2.js"></script>
<script async src="/js/app.js"></script>
<!-- Процесс:
Все три загружаются параллельно
Выполняются как только загружены (может быть любой порядок!)
Может быть: lib2 -> lib1 -> app
Может быть: lib1 -> app -> lib2
НЕ гарантирован порядок!
-->
<!-- С defer -->
<script defer src="/js/lib1.js"></script>
<script defer src="/js/lib2.js"></script>
<script defer src="/js/app.js"></script>
<!-- Процесс:
Все три загружаются параллельно
Выполняются в том же порядке что в коде
ГАРАНТИРОВАН порядок!
Всегда: lib1 -> lib2 -> app
-->
6. Динамически добавленный скрипт
// Добавляем скрипт через JavaScript
const script = document.createElement('script');
script.src = '/js/dynamic.js';
script.async = true; // или defer
document.body.appendChild(script);
// С обработкой загрузки
script.onload = () => {
console.log('Скрипт загружен!');
};
script.onerror = () => {
console.error('Ошибка загрузки скрипта');
};
Особенности:
- Загружается когда вызвана функция
- Полный контроль над моментом загрузки
- Можно обрабатывать onload/onerror
- Полезно для ленивой загрузки
7. Модули (ES6 modules)
<!-- Модуль с type="module" -->
<script type="module" src="/js/app.js"></script>
// app.js
import { getData } from './api.js';
import React from 'react';
const data = await getData();
Особенности:
- Автоматически defer (выполняется после парсинга)
- Поддержка import/export
- Scope модуля (переменные не глобальны)
- Асинхронная загрузка зависимостей
8. Встроенный модуль
<script type="module">
import { getData } from './api.js';
async function init() {
const data = await getData();
console.log(data);
}
init();
</script>
Таблица сравнения
| Способ | Загрузка | Выполнение | Блокировка | Порядок | Используй для |
|---|---|---|---|---|---|
| inline | Сразу | Сразу | ДА | N/A | Инициализация |
| head (sync) | Сразу | Сразу | ДА | Гарант. | Старые сайты |
| end body | Сразу | После DOM | НЕТ | Гарант. | Классические сайты |
| async | Фон | ASAP | НЕТ | НЕТ | Analytics, реклама |
| defer | Фон | После DOM | НЕТ | Гарант. | Основной app |
| dynamic | По требованию | По требованию | НЕТ | Управляемый | Ленивая загрузка |
| modules | Фон | После DOM | НЕТ | Гарант. | Современное приложение |
Практический пример: оптимальная структура
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>My App</title>
<!-- Критические стили -->
<style>
/* inline стили для above-the-fold контента */
</style>
<!-- Дополнительные стили -->
<link rel="stylesheet" href="/css/app.css">
<!-- Асинчронные скрипты третьих сторон -->
<script async src="https://www.googletagmanager.com/gtag/js"></script>
</head>
<body>
<div id="root"></div>
<!-- Основное приложение с defer -->
<script defer src="/js/vendor.js"></script>
<script defer src="/js/app.js"></script>
<!-- Или как модуль (рекомендуется) -->
<!-- <script type="module" src="/js/app.js"></script> -->
</body>
</html>
Лучшие практики
<!-- 1. Основной скрипт - используй defer -->
<script defer src="/js/app.js"></script>
<!-- 2. Независимый скрипт - используй async -->
<script async src="https://analytics.google.com"></script>
<!-- 3. Критический код - inline в head -->
<script>
window.theme = localStorage.getItem('theme');
</script>
<!-- 4. Модули - используй type="module" -->
<script type="module" src="/js/app.js"></script>
<!-- 5. Избегай sync загрузки в head -->
<!-- <script src="/js/app.js"></script> ❌ -->
<!-- 6. Используй dynamic loading для опциональных скриптов -->
<script>
if (userWantsFeature) {
const script = document.createElement('script');
script.src = '/js/feature.js';
document.body.appendChild(script);
}
</script>
Итого
Способы подключения скриптов от быстрого к медленному:
- defer - для основного приложения
- async - для независимых скриптов (analytics, реклама)
- modules - для современных приложений
- dynamic - для ленивой загрузки
- inline - для критического кода
- sync - избегай в production!
Мой выбор для современного приложения:
<script defer src="/js/vendor.bundle.js"></script>
<script defer src="/js/app.bundle.js"></script>
Или для модульного приложения:
<script type="module" src="/js/app.js"></script>