Оптимизация производительности в SPA

Библиотека AOS (Animate on Scroll) предназначена для анимации элементов при их появлении в области видимости при прокрутке страницы. Для начала необходимо подключить библиотеку к проекту. Можно использовать CDN или установить через npm:

<!-- Подключение через CDN -->
<link href="https://cdn.jsdelivr.net/npm/aos@2.3.4/dist/aos.css" rel="stylesheet">
<script src="https://cdn.jsdelivr.net/npm/aos@2.3.4/dist/aos.js"></script>

Или через npm:

npm install aos --save

Инициализация производится в Jav * aScript:

import AOS from 'aos';
import 'aos/dist/aos.css';

AOS.init({
  duration: 800,       // продолжительность анимации в миллисекундах
  once: true,          // анимация срабатывает один раз при первом скролле
  mirror: false,       // повторная анимация при прокрутке вверх
});

Основные атрибуты элементов

Анимации применяются к элементам с помощью атрибута data-aos. Например:

<div data-aos="fade-up" data-aos-delay="200" data-aos-duration="1000">
  Контент с анимацией
</div>

Ключевые параметры:

  • data-aos — тип анимации (fade-up, fade-down, zoom-in и др.).
  • data-aos-delay — задержка перед началом анимации (мс).
  • data-aos-duration — продолжительность анимации (мс).
  • data-aos-offset — смещение от начала видимости для запуска анимации.
  • data-aos-easing — функция сглаживания анимации (ease, ease-in-out, linear).

Особенности работы в SPA

В SPA (Single Page Application) страницы не перезагружаются полностью, что требует особого подхода:

  1. Повторная инициализация После изменения маршрута или динамического добавления элементов необходимо вызвать метод AOS.refresh() или AOS.refreshHard() для пересчёта позиций элементов:
// После добавления нового контента
AOS.refresh();

refresh пересчитывает позиции только для новых и изменённых элементов, тогда как refreshHard полностью пересоздаёт все элементы анимации.

  1. Динамическая подгрузка контента При загрузке данных через AJAX или fetch необходимо инициализировать анимации для новых элементов:
fetch('/api/data')
  .then(response => response.json())
  .then(data => {
    const container = document.getElementById('dynamic-container');
    data.forEach(item => {
      const div = document.createElement('div');
      div.setAttribute('data-aos', 'fade-up');
      div.textContent = item.text;
      container.appendChild(div);
    });
    AOS.refresh(); // пересчёт новых элементов
  });
  1. Оптимизация повторных рендеров В современных фреймворках (React, Vue, Angular) элементы могут часто пересоздаваться. Использование once: true минимизирует повторные вычисления и улучшает производительность.

Настройки для повышения производительности

1. Ограничение количества анимаций: Многочисленные анимированные элементы одновременно могут тормозить прокрутку. Для критических элементов используют анимацию только для ключевого контента.

2. Минимизация использования тяжелых анимаций: Анимации с масштабированием (scale) или сложным смещением (translate) требуют больше ресурсов. Предпочтение отдаётся fade или slide с минимальным количеством одновременно активных элементов.

3. Lazy loading и виртуализация: Для больших списков рекомендуется использовать ленивую подгрузку элементов и анимацию только видимых элементов. Например, с помощью Intersection Observer:

const observer = new IntersectionObserver(entries => {
  entries.forEach(entry => {
    if(entry.isIntersecting) {
      entry.target.setAttribute('data-aos', 'fade-up');
      AOS.refresh();
      observer.unobserve(entry.target);
    }
  });
});

document.querySelectorAll('.lazy-aos').forEach(el => observer.observe(el));

4. Использование AOS.refresh() экономно: Вызывать refresh только после добавления значительного количества новых элементов, а не на каждое событие прокрутки.

5. Настройка offset и duration: Слишком большие значения смещения или длительности анимации увеличивают нагрузку. Оптимальные значения: offset: 100-200, duration: 400-800 мс.

Интеграция с фреймворками

  • React: вызывать AOS.init() в useEffect при монтировании компонента, а AOS.refresh() после динамического обновления контента.
  • Vue: инициализация в mounted(), обновление через nextTick() после изменения DOM.
  • Angular: инициализация в ngAfterViewInit(), обновление после изменения данных с помощью ChangeDetectorRef.

Рекомендации по профилированию

  • Использовать инструменты браузера для анализа производительности (Performance в Chrome DevTools).
  • Проверять количество одновременно анимируемых элементов и FPS при прокрутке.
  • Сравнивать влияние once: true и mirror: true на рендеринг.
  • При необходимости отключать анимации на мобильных устройствах или для слабых устройств:
AOS.init({
  disable: 'mobile'
});

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