tRPCMiddleTechnical

Что такое links в tRPC? Объясните httpBatchLink, splitLink и loggerLink.

Links — это middleware-цепочка транспортного слоя tRPC. httpBatchLink группирует запросы в один HTTP-вызов, splitLink направляет запросы по условию на разные ссылки, loggerLink логирует все запросы и ответы для отладки.

Что такое links в tRPC

Links — это middleware-цепочка, которая обрабатывает каждый запрос клиента перед отправкой на сервер и каждый ответ перед возвратом в приложение. Они аналогичны middleware в Express или Apollo Link в GraphQL. Порядок в массиве links имеет значение: запрос проходит слева направо, ответ — справа налево. Последний link в цепочке должен быть terminating — он выполняет реальный HTTP-запрос.

httpBatchLink — батчинг запросов

Группирует несколько параллельных tRPC-запросов в один HTTP POST-запрос. Это критически важно для производительности: если компонент дерева вызывает 5 разных процедур одновременно, они отправятся как один запрос вместо пяти.

import { httpBatchLink } from '@trpc/client';

const client = trpc.createClient({
  links: [
    httpBatchLink({
      url: '/api/trpc',
      // Максимальный размер батча (по умолчанию без ограничений)
      maxURLLength: 2083,
      // Добавление заголовков ко всем запросам
      headers() {
        return {
          Authorization: `Bearer ${getToken()}`,
        };
      },
    }),
  ],
});

Батчинг работает с задержкой в одну микрозадачу — все запросы из одного рендер-цикла собираются вместе. Для отключения батчинга используйте httpLink вместо httpBatchLink.

splitLink — маршрутизация запросов

Направляет запросы на разные links в зависимости от условия. Типичный случай: subscriptions через WebSocket, остальные запросы через HTTP.

import { splitLink, httpBatchLink, wsLink, createWSClient } from '@trpc/client';

const wsClient = createWSClient({
  url: 'ws://localhost:3000/api/trpc',
  retryDelayMs: (attempt) => Math.min(1000 * 2 ** attempt, 30000),
});

const client = trpc.createClient({
  links: [
    splitLink({
      // Subscriptions идут через WebSocket
      condition: (op) => op.type === 'subscription',
      true: wsLink({ client: wsClient }),
      // Queries и mutations — через HTTP с батчингом
      false: httpBatchLink({ url: '/api/trpc' }),
    }),
  ],
});

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

loggerLink — логирование для отладки

Логирует все исходящие запросы и входящие ответы в консоль. Удобен при разработке для понимания, какие процедуры вызываются и что возвращается.

import { loggerLink, httpBatchLink } from '@trpc/client';

const client = trpc.createClient({
  links: [
    loggerLink({
      enabled: (opts) =>
        // Включён в development или при ошибках в любой среде
        process.env.NODE_ENV === 'development' ||
        (opts.direction === 'down' && opts.result instanceof Error),
      colorMode: 'ansi', // или 'css' для браузера
    }),
    httpBatchLink({ url: '/api/trpc' }),
  ],
});

Кастомный link

import { TRPCLink } from '@trpc/client';
import { observable } from '@trpc/server/observable';

const timingLink: TRPCLink<AppRouter> = () =>
  ({ next, op }) =>
    observable((observer) => {
      const start = Date.now();
      return next(op).subscribe({
        next(value) {
          console.log(`${op.path} took ${Date.now() - start}ms`);
          observer.next(value);
        },
        error: observer.error,
        complete: observer.complete,
      });
    });

Подводные камни

  • Порядок links в массиве фиксирован: loggerLink должен быть первым, terminating link (httpBatchLink) — последним. Перестановка нарушит логику.
  • httpBatchLink не работает с subscriptions — без splitLink WebSocket-подписки вызовут ошибку.
  • Батчинг может мешать отладке в DevTools: вместо отдельных запросов виден один POST с массивом. Для отладки временно заменяйте httpBatchLink на httpLink.
  • Слишком большой батч (много параллельных запросов) может превысить лимит размера URL или тела запроса на сервере — настраивайте maxURLLength.
  • loggerLink с включённым логированием в продакшене раскрывает структуру API и данные — ограничивайте его только через enabled: () => process.env.NODE_ENV === 'development'.
  • Кастомные links должны корректно пробрасывать и error, и complete — забытый complete приводит к утечкам памяти в observable-цепочке.

Common mistakes

  • Смешивать «links в tRPC» с похожим механизмом без критерия выбора.
  • Игнорировать риск: неверно оценить границы применения темы «links в tRPC» и получить хрупкое решение.
  • Показывать только синтаксис и не объяснять поведение в runtime или сборке.

What the interviewer is testing

  • Объясняет цепочка транспорта и побочных возможностей клиента.
  • Показывает на примере, как работает: links образуют pipeline для запроса: loggerLink логирует, splitLink выбирает ветку по operation, httpBatchLink объединяет HTTP-запросы, а subscription link обслуживает потоковые операции.
  • Называет production-нюанс и граничный случай для темы «links в tRPC».

Sources

Related topics