Code splitting

Tippy.js — это современная библиотека для создания всплывающих подсказок (tooltips) и легких попапов в веб-приложениях. Для эффективного использования в больших проектах часто применяют code splitting — стратегию разделения кода, позволяющую загружать библиотеки и модули только тогда, когда они реально необходимы.

Установка и базовое подключение

Библиотеку можно установить через npm или использовать CDN:

npm install @popperjs/core tippy.js

Для использования через ES-модули:

import tippy from 'tippy.js';
import 'tippy.js/dist/tippy.css';

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

Стратегия code splitting

Code splitting позволяет разбить приложение на отдельные чанки, которые подгружаются динамически. Для Tippy.js это особенно актуально, если всплывающие подсказки нужны не на каждой странице.

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

document.querySelectorAll('.tooltip-trigger').forEach(async (el) => {
  const { default: tippy } = await import('tippy.js');
  import('tippy.js/dist/tippy.css');

  tippy(el, {
    content: el.getAttribute('data-tooltip'),
    animation: 'fade',
    delay: [100, 50],
  });
});
  • await import('tippy.js') — динамически загружает библиотеку только при необходимости.
  • import('tippy.js/dist/tippy.css') — также позволяет загружать стили динамически, экономя ресурсы на страницах без подсказок.

Интеграция с сборщиками

Webpack

В конфигурации Webpack динамический импорт автоматически создаёт отдельный чанки. Для Tippy.js рекомендуется:

// В компоненте
const loadTippy = () => import('tippy.js').then(({ default: tippy }) => tippy);

document.querySelectorAll('.tooltip-trigger').forEach(async el => {
  const tippy = await loadTippy();
  tippy(el, { content: el.dataset.tooltip });
});

Дополнительно можно настроить webpackChunkName для удобного именования файлов:

const tippy = await import(/* webpackChunkName: "tippy" */ 'tippy.js').then(m => m.default);

Это позволяет легче отслеживать чанки в сети и оптимизировать кэширование.

Vite / ESBuild

Для Vite и ESBuild используется такой же синтаксис динамического импорта. Разница только в том, что сборщики автоматически создают отдельные файлы при import() без дополнительной настройки.

Lazy-loading плагинов Tippy.js

Tippy.js поддерживает плагины, например followCursor или sticky. Их также можно загружать динамически, чтобы уменьшить размер основного бандла:

const { default: tippy } = await import('tippy.js');
const { default: followCursor } = await import('tippy.js/dist/plugins/followCursor');

tippy('.tooltip-trigger', {
  content: 'Наведи на меня',
  plugins: [followCursor],
});

Особенности работы с CSS

Для динамического импорта стилей есть несколько подходов:

  1. Импорт через JavaScript (как показано выше).
  2. Использование <link rel="stylesheet" href="..."> с динамическим созданием тега:
const link = document.createElement('link');
link.rel = 'stylesheet';
link.href = 'https://unpkg.com/tippy.js@6/dist/tippy.css';
document.head.appendChild(link);

Этот метод подходит для приложений, где CSS не включен в основной бандл.

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

  • Минимизация количества вызовов Tippy: инициализация подсказок только на элементах, которые реально требуют интерактивности.
  • Динамическая загрузка только при взаимодействии: использовать mouseenter или focus для вызова импорта.
  • Использование кеширования чанков: современные сборщики позволяют кэшировать загруженные динамически файлы, снижая повторные загрузки.

Пример комплексной реализации

document.addEventListener('mouseover', async (e) => {
  const target = e.target.closest('.tooltip-trigger');
  if (!target || target.dataset.tippyInitialized) return;

  const [{ default: tippy },] = await Promise.all([
    import('tippy.js'),
    import('tippy.js/dist/tippy.css')
  ]);

  tippy(target, {
    content: target.dataset.tooltip,
    animation: 'scale',
    delay: [150, 100]
  });

  target.dataset.tippyInitialized = 'true';
});

В этом примере:

  • Подсказка и стили загружаются только при первом наведении.
  • Предотвращается повторная инициализация через флаг data-tippy-initialized.
  • Используется современный Promise.all для одновременной загрузки JS и CSS.

Эта стратегия позволяет эффективно интегрировать Tippy.js в масштабные веб-приложения, снижая нагрузку на основной бандл и ускоряя первичную загрузку страниц. Code splitting становится особенно важным при большом количестве зависимостей и плагинов.