Если ваш сайт открывается дольше трех секунд — половина посетителей уйдет, даже не дождавшись. Часто виноваты не картинки и не сервер, а скрипты. Они блокируют рендеринг страницы, заставляя браузер сидеть сложа руки. В этой статье я расскажу, как ускорить загрузку, не переписывая весь код, а просто правильно подключив и организовав скрипты. Поехали.
Что происходит, когда браузер встречает скрипт
Представьте: вы читаете книгу, и вдруг на полстраницы вставлена рекламная вкладка, которую нужно оторвать и прочитать, прежде чем продолжить. Вот так браузер воспринимает обычный скрипт в head или в середине страницы. Он останавливает чтение HTML, скачивает скрипт, выполняет его, и только потом двигается дальше. Если скриптов много или они тяжелые — страница замирает на несколько секунд.
Раньше это было нормой, но сейчас пользователи не прощают медленных сайтов. Поэтому главная задача — не дать скриптам блокировать показ контента. Для этого есть несколько проверенных способов.
Атрибуты defer и async: как подружить скрипты с загрузкой
Самый простой способ — добавить к тегу <script> атрибут defer или async. Они говорят браузеру: «скачивай скрипт параллельно с HTML, а выполнишь потом». Разница между ними в порядке выполнения.
Defer — скрипт скачивается в фоне, а выполняется строго после того, как весь HTML разобран. Важно: скрипты с defer выполняются в том порядке, в котором они написаны в коде. Это идеально для скриптов, которые зависят друг от друга.
Async — скрипт скачивается в фоне и выполняется сразу, как только скачался. Он не ждет ни HTML, ни другие скрипты. Порядок выполнения не гарантируется. Подходит для независимых скриптов: аналитика, реклама, виджеты.
<!-- Обычный скрипт — блокирует загрузку -->
<script src="heavy.js"></script>
<!-- Defer — ждет HTML, но не блокирует -->
<script src="heavy.js" defer></script>
<!-- Async — выполняется как только скачается -->
<script src="analytics.js" async></script>
Но есть нюанс: если скрипт вставлен в body в самом конце — defer не нужен, там он и так не блокирует почти ничего. А вот для скриптов в head — это спасение. Если скриптов несколько и они зависят друг от друга — используйте только defer. Если независимые — можно async.
Ленивая загрузка: когда скрипт не нужен сразу
Часто на странице есть скрипты, которые используются только при определенном действии пользователя: открытие модального окна, отправка формы, прокрутка к блоку с картой. Зачем грузить их при открытии сайта? Правильнее загрузить, когда понадобится. Это называется ленивой загрузкой.
Реализовать можно через динамический импорт в JavaScript или через атрибут loading="lazy" (но он работает только для iframe и img, для скриптов — нет). Поэтому чаще используют динамический import.
// Вместо того чтобы подключать скрипт в HTML, мы вызываем его по клику
document.getElementById('show-modal').addEventListener('click', async () => {
const { openModal } = await import('./modal.js');
openModal();
});
Этот код подгрузит файл modal.js только когда пользователь реально кликнет на кнопку. Все остальное время страница не тратит на него ресурсы.
Для старых браузеров можно использовать полифил, но современные все поддерживают динамический импорт. Если нужно поддерживать совсем древние — используйте классический подход: создайте скрипт, который добавляет тег <script> в DOM при необходимости.
function loadScript(src) {
return new Promise((resolve, reject) => {
const script = document.createElement('script');
script.src = src;
script.onload = resolve;
script.onerror = reject;
document.head.appendChild(script);
});
}
// Использование
loadScript('https://api.example.com/widget.js')
.then(() => { /* скрипт загружен */ })
.catch(err => console.error('Ошибка загрузки', err));
Оптимизация самого кода: меньше — значит быстрее
Даже если вы правильно подключите скрипты, но они будут весить по 500 КБ каждый — ничего хорошего. Оптимизация кода — это не только про красоту, но и про скорость.
Во-первых, используйте минификацию. Удалите все пробелы, комментарии, сократите имена переменных. Браузеру все равно, а размер файла уменьшится на 30-70%. Инструменты: UglifyJS, Terser, или сборщики типа Webpack и Vite.
Во-вторых, не тащите в проект целую библиотеку ради одной функции. Например, если нужна только сортировка массива — не подключайте Lodash целиком, возьмите маленькую функцию или напишите сами.
В-третьих, разбивайте код на маленькие модули и подключайте только то, что нужно для конкретной страницы. Это называется code splitting. Сборщики делают это автоматически, если использовать динамический импорт.
Вот пример, как не надо:
<!-- Подключаем всю библиотеку, а используем одну функцию -->
<script src="https://cdn.example.com/lodash.min.js"></script>
<script>
const sorted = _.sortBy([3, 1, 2]);
</script>
А так лучше:
// Сортируем без библиотеки
const sorted = [3, 1, 2].sort((a, b) => a - b);
Кэширование и CDN: ускоряем повторные визиты
Когда скрипт загрузился один раз, хорошо бы, чтобы при следующем визите браузер взял его из кэша, а не качал заново. Для этого на сервере должны быть правильные заголовки кэширования. Например, для статичных файлов можно выставлять Cache-Control: max-age=31536000 (год). Но если вы обновите скрипт, пользователи не увидят изменений. Поэтому обычно используют подход с хешем в имени файла: script.a1b2c3.js. Как только файл меняется — хеш меняется, и браузер скачивает новую версию.
Также используйте CDN (сеть доставки контента). Файлы будут отдаваться с сервера, ближайшего к пользователю. Это сокращает задержку в несколько раз. Популярные библиотеки можно подключать с общедоступных CDN, например, cdnjs или unpkg. Но если у вас свой код — лучше загружать его на свой CDN или использовать облачные хранилища с поддержкой CDN.
| Метод | Когда использовать | Эффект |
|---|---|---|
| defer | Скрипты, которые нужны для работы страницы, но не критичны для первого экрана | Не блокируют рендеринг, выполняются в порядке подключения |
| async | Независимые скрипты: аналитика, реклама | Не блокируют рендеринг, выполняются сразу после загрузки |
| Динамический импорт | Скрипты, которые нужны только по действию пользователя | Экономят трафик и ускоряют начальную загрузку |
| Минификация | Все скрипты перед продакшеном | Уменьшает размер файлов |
| Кэширование + CDN | Статичные файлы | Ускоряет повторные визиты, снижает нагрузку на сервер |
Инструменты для диагностики: что реально тормозит
Прежде чем оптимизировать, надо понять, что именно тормозит. Откройте DevTools в браузере (F12) и посмотрите вкладку Network. Там видно, какие скрипты грузятся дольше всего. Вкладка Performance покажет, сколько времени занимает выполнение JavaScript. Lighthouse (в Chrome) даст рекомендации по оптимизации.
Полезно также проверить сайт на PageSpeed Insights. Он покажет общую оценку и конкретные проблемы. Но не гонитесь за 100 баллами — достаточно 90+.
Итоговое резюме
Оптимизация загрузки скриптов — это не ракетостроение. Начните с простого:
- Добавьте
deferилиasyncко всем скриптам, которые не критичны для первого экрана. - Используйте динамический импорт для скриптов, которые нужны по действию.
- Минифицируйте код и разбивайте на модули.
- Настройте кэширование и подключите CDN.
- Проверяйте результат через DevTools и PageSpeed Insights.
Даже эти пять шагов могут ускорить загрузку в два-три раза. А быстрый сайт — это довольные пользователи и более высокие позиции в поисковиках. Так что не откладывайте — откройте консоль и посмотрите, что у вас там грузится.



