Shepherd.js — это библиотека для создания интерактивных пошаговых туров по веб-приложению. Как и любая динамическая библиотека, она требует внимательного подхода к управлению памятью. Неправильное использование Shepherd.js может привести к утечкам памяти, особенно при частом создании и уничтожении туров, динамических элементов DOM и подписок на события.
Основной объект Shepherd — Tour. Каждое создание нового
тура выделяет ресурсы, включая DOM-элементы подсказок
(Shepherd.Tour.addStep) и обработчики событий.
const tour = new Shepherd.Tour({
defaultStepOptions: {
scrollTo: true,
cancelIcon: { enabled: true }
}
});
tour.addStep({
id: 'intro',
text: 'Добро пожаловать!',
attachTo: { element: '.header', on: 'bottom' }
});
Ключевой момент: каждый созданный тур нужно
правильно завершать. Использование tour.complete() или
tour.cancel() освобождает связанные ресурсы. После
завершения рекомендуется удалять ссылки на объекты тура:
tour.complete();
tour = null; // Очистка ссылки для сборщика мусора
Без этой очистки объекты тура могут оставаться в памяти, особенно если туры создаются динамически при переходах между страницами.
Shepherd.js создает элементы подсказок (.shepherd-step)
и добавляет их в DOM. При множественном создании туров без удаления
старых шагов эти элементы накапливаются.
Правильная очистка DOM:
tour.steps.forEach(step => step.destroy());
Метод destroy() удаляет элементы подсказок и отвязывает
события, предотвращая накопление узлов в DOM. Не стоит полагаться на
автоматическую очистку при удалении тура — destroy() нужно
вызывать вручную.
Каждый шаг Shepherd.js может регистрировать обработчики событий:
step.on('show', () => console.log('Шаг показан'));
step.on('hide', () => console.log('Шаг скрыт'));
Опасность: если шаги уничтожаются без удаления слушателей, функции остаются в памяти, создавая утечки.
Решение: использовать метод off перед
уничтожением:
step.off('show');
step.off('hide');
step.destroy();
Или использовать tour.on и затем tour.off
для глобальных событий тура:
tour.on('complete', () => console.log('Тур завершен'));
// ...
tour.off('complete');
Если шаг прикреплен к динамически создаваемому элементу
(attachTo.element), важно учитывать, что при удалении
элемента DOM подсказка не уничтожается автоматически. Это приводит к
“висячим” элементам, которые удерживают память.
Рекомендации:
if (document.querySelector('.dynamic-element')) {
tour.show('dynamic-step');
}
const dynamicElement = document.querySelector('.dynamic-element');
dynamicElement.addEventListener('remove', () => {
step.destroy();
});
destroy и очищать
слушатели для каждого шага перед удалением туров.tour.cancel() для
корректного завершения активного тура при переходах между страницами или
компонентами SPA.let tour;
function initTour() {
tour = new Shepherd.Tour({ defaultStepOptions: { cancelIcon: { enabled: true } } });
tour.addStep({
id: 'step1',
text: 'Первый шаг',
attachTo: { element: '.header', on: 'bottom' }
});
tour.on('complete', cleanupTour);
tour.on('cancel', cleanupTour);
}
function cleanupTour() {
tour.steps.forEach(step => {
step.off();
step.destroy();
});
tour.off();
tour = null;
}
Такой подход гарантирует, что при завершении или отмене тура все элементы, события и ссылки на объекты освобождаются, предотвращая накопление памяти.
Для SPA и динамических приложений рекомендуется периодически
проверять использование памяти через инструменты браузера (Chrome
DevTools → Memory). Можно фиксировать количество шагов и туров перед и
после их создания и удаления. Любое неосвобожденное увеличение памяти
сигнализирует о потенциальных утечках, связанных с несвоевременным
вызовом destroy и off.
Управление памятью в Shepherd.js требует системного подхода: контролировать создание и уничтожение туров, шагов, событий и DOM-элементов. Правильная очистка предотвращает постепенное накопление памяти, особенно в долгоживущих веб-приложениях.