Логирование middleware

Floating UI — это библиотека для позиционирования всплывающих элементов в веб-приложениях. Одной из ключевых возможностей библиотеки является использование middleware, которые позволяют модифицировать поведение всплывающих элементов на лету. Логирование middleware представляет собой технику отслеживания работы этих промежуточных функций с целью отладки и анализа поведения интерфейса.

Понимание middleware в Floating UI

Middleware в Floating UI — это функции, которые получают объект middlewareArguments и возвращают модифицированный объект с данными о позиции или стилях. Типичная сигнатура middleware выглядит так:

function middlewareExample({ x, y, elements, placement }) {
  return { x: x + 10, y, data: {} };
}

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

  • x и y — текущие координаты позиции floating-элемента относительно reference-элемента.
  • elements — объект, содержащий ссылки на DOM-элементы reference и floating.
  • placement — текущее расположение floating-элемента (top, bottom, left, right).

Middleware выполняются последовательно, и каждый может изменять координаты или предоставлять дополнительную информацию через data. Именно эта последовательность делает middleware удобной точкой для внедрения логирования.

Реализация логирования middleware

Для логирования используется middleware, который не изменяет позицию элемента, а лишь записывает информацию о текущем состоянии. Пример:

import { offset, autoPlacement, computePosition } from '@floating-ui/dom';

function loggingMiddleware({ x, y, placement, elements, middlewareData }) {
  console.log('Middleware executed:');
  console.log('Coordinates:', { x, y });
  console.log('Placement:', placement);
  console.log('Reference element:', elements.reference);
  console.log('Floating element:', elements.floating);
  console.log('Middleware data:', middlewareData);
  return { x, y, data: middlewareData }; // Возвращаем неизмененные значения
}

async function positionFloating(reference, floating) {
  const { x, y, placement } = await computePosition(reference, floating, {
    middleware: [offset(10), loggingMiddleware, autoPlacement()],
  });
  
  Object.assign(floating.style, {
    left: `${x}px`,
    top: `${y}px`,
  });
}

Особенности подхода:

  • Middleware может выводить информацию о каждом шаге позиционирования.
  • middlewareData позволяет логировать данные, передаваемые между промежуточными функциями.
  • Логирование не мешает работе других middleware, если возвращаются исходные координаты.

Использование middlewareData для детального анализа

Каждое middleware может добавлять данные в объект middlewareData, который передаётся следующему middleware. Это удобно для мониторинга промежуточных расчётов. Пример расширенного логирования:

function debugMiddleware({ x, y, placement, middlewareData }) {
  const timestamp = new Date().toISOString();
  const logEntry = { x, y, placement, timestamp };
  
  middlewareData.debugLogs = middlewareData.debugLogs || [];
  middlewareData.debugLogs.push(logEntry);
  
  console.table(middlewareData.debugLogs);
  return { x, y, data: middlewareData };
}

Преимущества такого подхода:

  • Позволяет проследить последовательность изменений координат и позиций.
  • Удобно для отладки сложных систем с динамическим позиционированием.
  • Можно накапливать и анализировать логи без вмешательства в основной поток вычислений.

Логирование событий при динамических изменениях

Floating UI предоставляет возможность автоматически обновлять позицию элемента при изменении размера окна или контента. Для таких сценариев логирование middleware помогает отслеживать изменения в реальном времени:

import { autoUpdate } from '@floating-ui/dom';

const cleanup = autoUpdate(reference, floating, async () => {
  const { x, y, placement } = await computePosition(reference, floating, {
    middleware: [offset(10), debugMiddleware, autoPlacement()],
  });

  Object.assign(floating.style, { left: `${x}px`, top: `${y}px` });
});

// Для остановки обновлений
// cleanup();

Использование autoUpdate вместе с логирующим middleware позволяет видеть:

  • Как часто пересчитывается позиция.
  • Какие middleware изменяют координаты.
  • Реальные значения placement при разных размерах окна.

Практические рекомендации по логированию

  • Сохранять данные в объекте middlewareData, а не только в консоли, чтобы использовать их для анализа после серии событий.
  • Минимизировать вычислительную нагрузку: логирование не должно замедлять позиционирование. Можно выводить логи через requestAnimationFrame или накапливать их в массив.
  • Именовать middleware осмысленно, например logPositionMiddleware или debugFloatingMiddleware, чтобы понимать их назначение в цепочке.
  • Фильтровать логи по уровню важности, особенно в продакшн-окружении, используя условия или флаги.

Интеграция с внешними системами логирования

Можно отправлять данные middleware в сторонние сервисы аналитики, что полезно для UI-команд, отлаживающих сложные всплывающие элементы:

function analyticsMiddleware({ x, y, placement, middlewareData }) {
  fetch('/log-position', {
    method: 'POST',
    body: JSON.stringify({ x, y, placement, timestamp: Date.now() }),
    headers: { 'Content-Type': 'application/json' },
  });
  return { x, y, data: middlewareData };
}

Такой подход позволяет собирать статистику о взаимодействии пользователей с floating-элементами и выявлять проблемы с позиционированием на разных устройствах.


Логирование middleware в Floating UI — это мощный инструмент для анализа и отладки позиционирования. Оно позволяет отслеживать работу всех промежуточных функций, накапливать данные о координатах и событиях, а также интегрироваться с системами аналитики без вмешательства в основную логику приложения.