Сайт грузится медленно, кнопки не работают, а пользователи уходят? Часто виноват JavaScript. Давай разберёмся, как заставить скрипты работать быстро и не мешать остальному.

Digital-студия WNDER

Почему JavaScript может тормозить загрузку страницы

Когда браузер встречает тег <script>, он останавливает построение DOM, скачивает скрипт и выполняет его. Если скрипт тяжёлый или их много, страница белеет и ждёт. Это как если бы ты собирал шкаф, а тебя постоянно дёргали с вопросами.

Есть три основные проблемы:

  • Блокировка рендеринга — браузер не показывает контент, пока не выполнит скрипт.
  • Большой размер файлов — чем больше кода, тем дольше скачивание и парсинг.
  • Долгое выполнение — тяжёлые вычисления замораживают интерфейс.

Чтобы этого избежать, нужно правильно подключать скрипты и оптимизировать их выполнение.

Способы подключения скриптов: async, defer и не только

По умолчанию скрипт блокирует парсинг. Но есть атрибуты async и defer, которые меняют поведение.

Атрибут Когда скачивается Когда выполняется Блокирует парсинг?
без атрибутов сразу сразу после скачивания Да
async параллельно с парсингом как только скачается (может прервать парсинг) Нет, но выполнение может прервать
defer параллельно с парсингом после завершения парсинга Нет

Используй defer для скриптов, которые зависят от DOM или других скриптов. async подойдёт для независимых модулей, например счётчиков.

Правило: Всегда ставь defer для основных скриптов, если нет причин использовать async. Это ускорит отображение страницы.

Минификация, сжатие и разделение кода

Чем меньше кода, тем быстрее он загружается. Минификация убирает пробелы, комментарии и сокращает имена переменных. Сжатие (gzip, brotli) уменьшает размер при передаче.

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

// Вместо import { heavyFunction } from './heavyModule.js';
// Используй динамический импорт
button.addEventListener('click', async () => {
  const { heavyFunction } = await import('./heavyModule.js');
  heavyFunction();
});

Такой подход называется code splitting. Он позволяет загружать код по требованию.

Оптимизация выполнения: не блокируй главный поток

JavaScript однопоточный. Если выполняется долгая задача, интерфейс замирает. Например, обработка большого массива или сложные вычисления.

Решение — разбивать задачи на части или использовать Web Workers. Web Workers выполняют код в фоновом потоке, не блокируя UI.

// main.js
const worker = new Worker('worker.js');
worker.postMessage({ data: bigArray });
worker.onmessage = (event) => {
  console.log('Результат:', event.data);
};

// worker.js
self.onmessage = (event) => {
  const result = heavyProcessing(event.data);
  self.postMessage(result);
};

Также используй requestAnimationFrame для анимаций и setTimeout с нулевой задержкой для разбиения длинных задач.

Лайфхак: Если нужно выполнить тяжёлую операцию, разбей её на части с помощью setTimeout или requestIdleCallback, чтобы не блокировать интерфейс.

Кэширование и предзагрузка

Браузер кэширует скрипты, но можно управлять этим с помощью HTTP-заголовков. Установи Cache-Control: max-age=31536000 для статических файлов. Но если файл обновился, нужно менять имя (хеш) или использовать версионирование.

Для предзагрузки критичных скриптов используй <link rel="preload">:

<link rel="preload" href="critical.js" as="script">

Это заставит браузер скачать скрипт с высоким приоритетом, не блокируя парсинг.

Инструменты для анализа и оптимизации

Чтобы понять, что тормозит, используй Lighthouse, WebPageTest, Chrome DevTools (вкладка Performance). Они покажут, какие скрипты долго загружаются или выполняются.

Также полезно проверять размер бандла с помощью Webpack Bundle Analyzer. Он покажет, какие модули занимают больше всего места.

Не забывай про tree shaking — удаление неиспользуемого кода. Современные сборщики (Webpack, Rollup) делают это автоматически, если использовать ES-модули.

Что в итоге

Оптимизация JavaScript — это не магия, а набор простых действий. Подключай скрипты с defer, минифицируй и сжимай код, разделяй на модули, не блокируй главный поток и анализируй производительность. Начни с малого: проверь свои скрипты и добавь defer. Ты удивишься, насколько быстрее станет сайт.

Студия WNDER