Отложенная загрузка скриптов

Отложенная загрузка скриптов (lazy loading) в контексте работы с Locomotive Scroll критически важна для обеспечения плавного скроллинга и предотвращения тормозов при инициализации страницы. В библиотеке Locomotive Scroll элементы страницы, особенно с эффектами параллакса, привязаны к DOM-структуре и размерам контейнера. Если скрипты и контент загружаются асинхронно, необходимо корректно обновлять расчёты прокрутки, чтобы анимации и позиционирование элементов оставались точными.

Подключение скриптов с атрибутами defer и async

  1. Defer Скрипт с defer загружается параллельно с HTML и выполняется после того, как весь документ будет разобран. Это идеально подходит для Locomotive Scroll, так как инициализация происходит после полной загрузки DOM.

    <script src="locomotive-scroll.min.js" defer></script>
    <script src="app.js" defer></script>

    В таком случае можно безопасно вызвать:

    const scroll = new LocomotiveScroll({
        el: document.querySelector('#scroll-container'),
        smooth: true,
        multiplier: 1.2
    });

    после полной загрузки DOM, без риска, что контейнер ещё не существует.

  2. Async Скрипт с async выполняется сразу после загрузки, не дожидаясь HTML. При использовании async важно учитывать порядок зависимостей: если Locomotive Scroll загружается async, но инициализация скрипта происходит раньше, чем библиотека доступна, возникнет ошибка. Поэтому для основной логики Locomotive Scroll defer предпочтительнее.

Асинхронная подгрузка контента и обновление скролла

Locomotive Scroll хранит внутреннее состояние элементов, их позиции и размеры. Любые динамические изменения DOM требуют вызова метода:

scroll.update();

Примеры ситуаций, когда необходимо обновление:

  • Подгрузка изображений через lazy loading (<img loading="lazy">)
  • Асинхронная вставка блоков контента (fetch + innerHTML)
  • Динамическая смена высоты контейнеров

Пример с динамической подгрузкой контента:

fetch('/api/articles')
  .then(response => response.json())
  .then(data => {
      const container = document.querySelector('#scroll-content');
      data.forEach(item => {
          const div = document.createElement('div');
          div.className = 'article-item';
          div.innerHTML = `<h2>${item.title}</h2><p>${item.text}</p>`;
          container.appendChild(div);
      });
      scroll.update(); // обновление расчётов после добавления контента
  });

Отложенная инициализация Locomotive Scroll

Если страница содержит тяжелые анимации или большое количество элементов, инициализацию библиотеки можно выполнять только после загрузки основных ресурсов:

window.addEventListener('load', () => {
    const scroll = new LocomotiveScroll({
        el: document.querySelector('#scroll-container'),
        smooth: true
    });
});

Такой подход предотвращает подвисания при старте и позволяет плавно интегрировать скролл с асинхронными библиотеками анимаций (например, GSAP).

Интеграция с lazy loading изображений

При использовании библиотек lazy loading изображений (lazysizes, IntersectionObserver) важно после загрузки каждого изображения оповещать Locomotive Scroll:

document.addEventListener('lazyloaded', function(e){
    scroll.update();
});

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

Взаимодействие с динамическими компонентами

В SPA или при работе с фреймворками (React, Vue, Svelte) DOM может меняться после первоначальной отрисовки. Для сохранения корректной работы Locomotive Scroll необходимо:

  1. Инициализировать скролл после полной монтировки контейнера.
  2. Вызывать scroll.update() после любого изменения высоты или добавления элементов.
  3. При удалении элементов использовать scroll.destroy() перед повторной инициализацией, если контейнер полностью меняется.

Практические рекомендации

  • Использовать defer для загрузки Locomotive Scroll и основного скрипта, чтобы избежать ошибок выполнения.
  • Для тяжелых страниц лучше инициализировать скролл на событие window.load.
  • Всегда вызывать scroll.update() после асинхронной подгрузки элементов.
  • Интегрировать с lazy loading изображений через событие lazyloaded.
  • При полной перерисовке контейнера — scroll.destroy() и повторная инициализация.

Эти методы обеспечивают корректную работу скролла, предотвращают скачки контента и делают анимации плавными даже при динамической загрузке ресурсов.