Code Splitting — это методика разделения кода на отдельные чанки, которые загружаются по мере необходимости. В контексте ScrollMagic это особенно важно, так как библиотеки для анимаций и управления скроллом часто весят немало и могут замедлять первичную загрузку страницы.
ScrollMagic сам по себе небольшой, но его плагины и зависимости (GSAP, анимации на CSS, контроллеры и сцены) могут существенно увеличивать размер бандла. Использование code splitting позволяет загружать основные скрипты сразу, а сложные анимации — только тогда, когда они становятся актуальными.
В ScrollMagic ключевым объектом является Controller, который управляет всеми сценами (Scene). Каждая сцена может быть отдельной анимацией, привязанной к скроллу.
Пример структуры с code splitting:
// main.js
import ScrollMagic from "scrollmagic";
const controller = new ScrollMagic.Controller();
document.addEventListener("DOMContentLoaded", async () => {
if (window.location.pathname === "/homepage") {
const { initHomepageScenes } = await import("./scenes/homepage.js");
initHomepageScenes(controller);
}
if (window.location.pathname === "/about") {
const { initAboutScenes } = await import("./scenes/about.js");
initAboutScenes(controller);
}
});
В этом примере каждая страница загружает только нужные сцены, а основной бандл остаётся минимальным.
Многие эффекты ScrollMagic зависят от GSAP. Чтобы не тянуть всю библиотеку сразу, её также можно загружать динамически:
async function loadAnimation(sceneSelector) {
const { gsap } = await import("gsap");
const { ScrollMagicPluginGsap } = await import("scrollmagic-plugin-gsap");
ScrollMagicPluginGsap(ScrollMagic, gsap);
const scene = new ScrollMagic.Scene({
triggerElement: sceneSelector,
duration: 500
})
.setTween(gsap.to(sceneSelector, { opacity: 1, y: 50 }))
.addTo(controller);
}
Загрузка GSAP и плагина происходит только при необходимости, что ускоряет первичный рендер страницы.
В больших проектах есть смысл откладывать создание сцен до момента, когда пользователь почти доходит до нужного блока. Это делается с помощью простого отслеживания видимости элементов:
const sections = document.querySelectorAll(".scroll-section");
sections.forEach(section => {
const observer = new IntersectionObserver(async (entries) => {
if (entries[0].isIntersecting) {
const { createScene } = await import(`./scenes/${section.dataset.scene}.js`);
createScene(controller, section);
observer.unobserve(section);
}
}, { threshold: 0.5 });
observer.observe(section);
});
Каждая сцена загружается только тогда, когда она становится видимой хотя бы на 50% блока.
Для сборщиков вроде Webpack можно настроить dynamic import, который создаёт отдельные чанки автоматически:
// webpack.config.js
module.exports = {
output: {
filename: "[name].bundle.js",
chunkFilename: "[name].chunk.js"
},
optimization: {
splitChunks: {
chunks: "all",
maxInitialRequests: 5,
minSize: 20000
}
}
};
Такой подход позволяет автоматически делить основной код и код сцен, включая плагины GSAP, ScrollMagic и пользовательские модули.
scene.destroy() после их завершения или выхода за пределы
видимости, чтобы не накапливать лишние обработчики.// scenes/homepage.js
import ScrollMagic from "scrollmagic";
export function initHomepageScenes(controller) {
const scene1 = new ScrollMagic.Scene({
triggerElement: "#hero",
duration: 400
})
.setClassToggle("#hero", "fade-in")
.addTo(controller);
const scene2 = new ScrollMagic.Scene({
triggerElement: "#features",
duration: 600
})
.setClassToggle("#features", "slide-up")
.addTo(controller);
}
Каждая сцена оформлена как отдельная функция, что упрощает динамический импорт и поддерживает разделение кода.
Такой подход позволяет поддерживать высокую производительность, уменьшает время первичной загрузки страницы и делает работу с ScrollMagic более модульной и гибкой.