Логирование переходов

Page.js — это микробиблиотека для маршрутизации на стороне клиента в одностраничных приложениях (SPA). Одной из ключевых задач при работе с маршрутизатором является логирование переходов, которое позволяет отслеживать историю навигации, анализировать поведение пользователя и выявлять ошибки маршрутизации.


Подключение и настройка Page.js

Для начала необходимо подключить библиотеку:

import page from 'page';

После подключения создаются маршруты с использованием функции page(path, callback). Каждое перемещение по маршруту можно перехватывать и логировать:

page('/home', () => {
  console.log('Перешли на страницу Home');
});

page('/about', () => {
  console.log('Перешли на страницу About');
});

page.start();

Здесь ключевой момент — каждый маршрут имеет собственный обработчик, и вызов console.log внутри него обеспечивает базовое логирование.


Глобальное логирование всех переходов

Иногда требуется логировать все переходы, независимо от маршрута. Page.js предоставляет хук page('*', callback), который срабатывает на любом маршруте:

page('*', (ctx, next) => {
  console.log(`[LOG] Переход на: ${ctx.path}`);
  next();
});
  • ctx.path — полный путь маршрута.
  • ctx.params — объект с параметрами маршрута.
  • ctx.querystring — строка запроса после ?.

Вызов next() передает управление следующему обработчику, поэтому важно не забывать его использовать для корректной работы цепочки маршрутов.


Логирование с информацией о параметрах

Маршруты с динамическими сегментами позволяют получать параметры URL:

page('/user/:id', (ctx) => {
  console.log(`Перешли на страницу пользователя с ID: ${ctx.params.id}`);
});

Пример с несколькими параметрами:

page('/order/:orderId/item/:itemId', (ctx) => {
  console.log(`Order: ${ctx.params.orderId}, Item: ${ctx.params.itemId}`);
});

Использование параметров упрощает анализ навигации и позволяет связывать действия пользователя с конкретными объектами.


Логирование query-параметров

Query-параметры (?key=value) часто используются для фильтров или поиска. Для их логирования необходимо парсить ctx.querystring:

page('/search', (ctx) => {
  const query = new URLSearchParams(ctx.querystring);
  console.log(`Поиск с параметрами: ${JSON.stringify(Object.fromEntries(query))}`);
});

URLSearchParams позволяет легко конвертировать строку запроса в объект для удобного логирования.


Ведение истории переходов

Для полноценного логирования полезно хранить историю переходов в массиве:

const history = [];

page('*', (ctx, next) => {
  history.push({ path: ctx.path, time: new Date().toISOString() });
  next();
});

// Позже можно вывести историю
console.table(history);

Такой подход позволяет анализировать последовательность переходов, выявлять повторяющиеся маршруты и проводить статистику посещений.


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

Page.js легко интегрируется с аналитическими сервисами:

page('*', (ctx, next) => {
  sendToAnalytics({
    path: ctx.path,
    params: ctx.params,
    query: ctx.querystring,
    timestamp: Date.now()
  });
  next();
});

function sendToAnalytics(data) {
  fetch('/analytics', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify(data)
  });
}

Можно отправлять данные в серверные системы или сторонние платформы аналитики (Google Analytics, Yandex.Metrika), что делает логирование централизованным и удобным для последующего анализа.


Логирование с фильтрацией и приоритетами

В сложных приложениях может потребоваться фильтрация маршрутов для логирования:

page('*', (ctx, next) => {
  if (!ctx.path.startsWith('/admin')) {
    console.log(`[USER LOG] ${ctx.path}`);
  }
  next();
});

Также можно управлять порядком обработки переходов, создавая несколько middleware с разной приоритетностью:

page((ctx, next) => {
  console.log('Первый middleware');
  next();
});

page((ctx, next) => {
  console.log('Второй middleware');
  next();
});

Page.js обрабатывает middleware последовательно в порядке их объявления.


Асинхронное логирование

Для отправки данных на сервер без блокировки навигации можно использовать асинхронные функции:

page('*', async (ctx, next) => {
  await logToServer(ctx.path);
  next();
});

async function logToServer(path) {
  try {
    await fetch('/log', { method: 'POST', body: JSON.stringify({ path }) });
  } catch (e) {
    console.error('Ошибка логирования', e);
  }
}

Асинхронность гарантирует, что переход произойдет без задержки для пользователя, а данные о маршруте будут отправлены надежно.


Логирование ошибок при навигации

Важно отслеживать ошибки при переходах, чтобы понимать, когда маршруты не срабатывают:

page('*', (ctx, next) => {
  try {
    next();
  } catch (error) {
    console.error(`Ошибка при переходе на ${ctx.path}:`, error);
  }
});

Такой подход обеспечивает безопасное логирование и позволяет выявлять недоступные маршруты или исключения в обработчиках.


Поддержка SPA с динамическим контентом

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

page('/products/:id', async (ctx) => {
  const product = await fetchProduct(ctx.params.id);
  console.log(`Открыт продукт: ${product.name}`);
});

Логирование сочетает в себе параметры маршрута, query-параметры и данные, загруженные асинхронно, что делает анализ поведения пользователя более полным.