Если ваш сайт грузится дольше трёх секунд — половина посетителей уйдёт, даже не дождавшись. Часто виноват не хостинг и не PHP, а JavaScript, который блокирует отрисовку страницы. В этой статье разберём, как ускорить загрузку и выполнение скриптов, не превращая код в кашу. Вы узнаете, какие атрибуты спасают, а какие — вредят, и как применять современные методы без боли.

Digital-студия WNDER

Ссылка на оригинальную статью

Что происходит, когда браузер встречает script

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

Такой подход называется блокирующим. Он гарантирует, что скрипт выполнится до того, как пользователь что-то увидит, но ценой скорости. Особенно плохо, если скриптов много или они тяжёлые.

Атрибуты defer и async: как не блокировать загрузку

Чтобы браузер не останавливался, придумали два атрибута: defer и async. Они говорят браузеру: «скачивай скрипт в фоне, а выполнишь потом». Но между ними есть разница.

Атрибут Когда скачивается Когда выполняется Порядок выполнения
defer Параллельно с парсингом HTML После полного разбора документа В порядке появления в HTML
async Параллельно с парсингом HTML Сразу после скачивания Не гарантируется

Правило: если скрипт зависит от других скриптов или от DOM — используйте defer. Если скрипт независим (например, счётчик аналитики) — async.

Пример правильного подключения:

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

Минификация и сжатие: делаем файлы легче

Когда вы пишете код, вы ставите пробелы, переносы строк, комментарии — это удобно для чтения, но браузеру всё равно. Минификация убирает лишнее, уменьшая размер файла на 30-50%.

Сжатие (gzip или brotli) — это как упаковка чемодана вакуумным пакетом. Сервер сжимает файл, браузер распаковывает. Разница в скорости загрузки ощутима.

Как это делается на PHP? Например, можно настроить сжатие через .htaccess:

<IfModule mod_deflate.c>
  AddOutputFilterByType DEFLATE text/javascript application/javascript
</IfModule>

Или использовать PHP-функцию ob_gzhandler:

ob_start('ob_gzhandler');
// остальной код

Лайфхак: используйте сборщики (Webpack, Vite), чтобы автоматически минифицировать скрипты при сборке. Это экономит время и исключает ошибки.

Code splitting: грузите только то, что нужно

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

Code splitting (разделение кода) позволяет разбить скрипт на части и загружать их по мере необходимости. Это делается с помощью динамического импорта:

// Вместо того чтобы подключать слайдер статически
// import Slider from './slider';

// Делаем динамический импорт, когда он нужен
async function initSlider() {
  const { default: Slider } = await import('./slider');
  new Slider('#my-slider');
}

Браузер загрузит слайдер только тогда, когда вызовется функция initSlider. Это ускоряет первую загрузку страницы.

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

JavaScript выполняется в одном потоке. Если скрипт делает тяжёлые вычисления, страница «зависает». Пользователь видит белый экран или невозможность кликнуть.

Чтобы этого избежать, разбивайте тяжёлые задачи на части или используйте requestAnimationFrame для анимаций и setTimeout для отложенных операций.

Пример разбиения тяжёлого цикла:

function processLargeArray(items) {
  let index = 0;

  function processChunk() {
    const chunkSize = 100;
    for (let i = 0; i < chunkSize && index < items.length; i++, index++) {
      // тяжёлая обработка элемента
      heavyOperation(items[index]);
    }
    if (index < items.length) {
      // откладываем следующий кусок
      setTimeout(processChunk, 0);
    }
  }

  processChunk();
}

Этот подход заставляет браузер дышать, а не задыхаться.

Правило: если скрипт выполняется дольше 50 миллисекунд, он блокирует взаимодействие с страницей. Разбивайте большие задачи на куски по 10-20 миллисекунд.

Практические советы для PHP-разработчиков

Вы пишете на PHP, но JavaScript — ваш постоянный спутник. Вот что можно сделать прямо сейчас:

  • Переносите скрипты в конец страницы перед </body>, если не используете defer.
  • Используйте атрибут defer для скриптов, которые должны выполниться после загрузки DOM.
  • Проверяйте размер скриптов в DevTools: если больше 100 КБ — задумайтесь о разделении.
  • Настройте кеширование на сервере, чтобы браузер не скачивал скрипты повторно.
  • Используйте CDN для популярных библиотек (jQuery, React) — они могут быть уже в кеше у пользователя.

Пример настройки кеширования в PHP:

header("Cache-Control: public, max-age=31536000");
header("Expires: " . gmdate("D, d M Y H:i:s", time() + 31536000) . " GMT");

Что в итоге

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

Помните: скорость — это не роскошь, а необходимость. Каждая секунда задержки — это потерянные посетители и деньги.

Студия WNDER