Кеширование результатов loader'ов

TanStack Router предоставляет мощный механизм для управления данными при маршрутизации, включая loader’ы — функции, отвечающие за загрузку данных перед рендерингом маршрута. Одним из ключевых аспектов оптимизации производительности является кеширование результатов loader’ов, позволяющее избегать лишних сетевых запросов и ускорять навигацию по приложению.


Принципы работы loader’ов

Loader — это асинхронная функция, связанная с маршрутом, которая возвращает данные для компонента. TanStack Router вызывает loader при первой навигации на маршрут или при изменении параметров маршрута, если они влияют на результат загрузки.

Пример простого loader’а:

import { createRouter, createRoute } from '@tanstack/router';

const userRoute = createRoute({
  path: '/user/:id',
  loader: async ({ params }) => {
    const response = await fetch(`/api/users/${params.id}`);
    return response.json();
  },
});

Без кеширования каждый переход к /user/:id будет инициировать новый сетевой запрос, даже если данные уже были загружены ранее.


Встроенное кеширование TanStack Router

TanStack Router имеет встроенную систему кеширования по маршруту и параметрам. Loader возвращает промис, который TanStack Router автоматически кеширует, если используется cacheTime или staleTime.

  • cacheTime — время жизни кеша до его автоматического сброса.
  • staleTime — период, в течение которого данные считаются актуальными. После этого TanStack Router может повторно вызывать loader при навигации.

Пример использования опций кеширования:

const userRoute = createRoute({
  path: '/user/:id',
  loader: async ({ params }) => {
    const response = await fetch(`/api/users/${params.id}`);
    return response.json();
  },
  cacheTime: 1000 * 60 * 5, // 5 минут
  staleTime: 1000 * 60,     // 1 минута
});

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


Кеширование на уровне запроса

Можно организовать кеширование так, чтобы данные для одного и того же запроса не загружались повторно, даже при множественных вызовах loader’а с одинаковыми параметрами. Для этого TanStack Router использует ключи запроса, формируемые на основе маршрута и параметров.

const postRoute = createRoute({
  path: '/posts/:postId',
  loader: async ({ params }) => {
    const cacheKey = `post-${params.postId}`;
    if (localStorage.getItem(cacheKey)) {
      return JSON.parse(localStorage.getItem(cacheKey));
    }

    const response = await fetch(`/api/posts/${params.postId}`);
    const data = await response.json();
    localStorage.setItem(cacheKey, JSON.stringify(data));
    return data;
  },
});

Такой подход позволяет комбинировать внутреннее кеширование TanStack Router и внешний механизм хранения, например localStorage или IndexedDB.


Управление устаревшими данными

TanStack Router предоставляет инструменты для явного контроля устаревших данных:

  • router.invalidate() — сбрасывает кеш для определённого маршрута.
  • router.prefetch() — загружает данные заранее, используя кеширование.
  • router.reload() — повторно вызывает loader, игнорируя кеш.

Пример принудительной инвалидизации:

router.invalidate({ routeId: 'userRoute', params: { id: 123 } });

После вызова данных loader для маршрута /user/123 будет загружен заново при следующей навигации.


Комбинирование кеширования и реактивного состояния

TanStack Router позволяет использовать результаты loader’ов вместе с реактивными библиотеками (например, React). Например, можно кешировать данные в loader и автоматически обновлять компонент при изменении данных:

const userRoute = createRoute({
  path: '/user/:id',
  loader: async ({ params }) => {
    const response = await fetch(`/api/users/${params.id}`);
    return response.json();
  },
});

function UserComponent({ route }) {
  const user = route.useLoaderData();
  return <div>{user.name}</div>;
}

Если кеш не устарел, useLoaderData() вернёт данные мгновенно без повторного запроса.


Практические советы по кешированию loader’ов

  1. Использовать staleTime для часто обновляемых данных, чтобы минимизировать сетевой трафик, но не показывать устаревшую информацию слишком долго.
  2. Использовать cacheTime для редко изменяющихся данных, например, справочников или статической информации.
  3. Комбинировать внутренний кеш маршрутизатора с внешним, если требуется кэшировать на длительное время между перезагрузками страницы.
  4. Явно инвалидировать кеш при обновлении данных на сервере, чтобы избежать показа устаревшей информации.
  5. Группировать данные по ключам, чтобы один и тот же loader не создавал дублирующие запросы при одинаковых параметрах.

Кеширование loader’ов в TanStack Router — это не просто оптимизация скорости. Это инструмент для контроля данных, снижения нагрузки на сервер и построения предсказуемого пользовательского опыта. Гибкость параметров cacheTime, staleTime и возможностей явной инвалидизации позволяет создавать маршруты, которые одновременно быстрые, актуальные и надежные.