tRPCMiddleTechnical

Чем tRPC v11 отличается от v10? Какие breaking changes были введены?

tRPC v11 переработал транспортный слой: httpSubscriptionLink для SSE-подписок без WebSocket, поддержка формдата, трансформеры переехали в links. Breaking changes: новый API инициализации, изменённые типы контекста, обновлённый fetchRequestHandler.

Ключевые нововведения tRPC v11

1. httpSubscriptionLink — SSE без WebSocket

В v10 единственный способ подписок — WebSocket через wsLink. v11 добавляет httpSubscriptionLink, который использует Server-Sent Events (SSE). Это проще в деплое: не нужен отдельный WebSocket-сервер, работает через стандартный HTTP.

// v11: SSE подписки
import { createTRPCClient, httpBatchLink, httpSubscriptionLink, splitLink } from '@trpc/client';

const client = createTRPCClient<AppRouter>({
  links: [
    splitLink({
      condition: (op) => op.type === 'subscription',
      true: httpSubscriptionLink({ url: '/api/trpc' }), // SSE!
      false: httpBatchLink({ url: '/api/trpc' }),
    }),
  ],
});

2. Трансформеры переехали в links

В v10 трансформер задавался глобально при инициализации клиента. В v11 он передаётся напрямую в каждый link — это даёт гибкость: разные links могут использовать разные трансформеры.

// v10 (устарело)
const client = createTRPCProxyClient<AppRouter>({
  transformer: superjson, // глобально
  links: [httpBatchLink({ url: '/api/trpc' })],
});

// v11 (новый подход)
import superjson from 'superjson';

const client = createTRPCClient<AppRouter>({
  links: [
    httpBatchLink({
      url: '/api/trpc',
      transformer: superjson, // в link
    }),
  ],
});

3. createTRPCClient вместо createTRPCProxyClient

createTRPCProxyClient переименован в createTRPCClient. Старое имя оставлено как deprecated alias, но рекомендуется обновить импорты.

// v10
import { createTRPCProxyClient } from '@trpc/client';

// v11
import { createTRPCClient } from '@trpc/client';

4. fetchRequestHandler обновлён

Адаптер для Edge Runtime и App Router стал основным вместо createNextApiHandler. API немного изменился:

// app/api/trpc/[trpc]/route.ts (v11)
import { fetchRequestHandler } from '@trpc/server/adapters/fetch';
import { appRouter } from '../../../../server/trpc/router';

const handler = (req: Request) =>
  fetchRequestHandler({
    endpoint: '/api/trpc',
    req,
    router: appRouter,
    createContext: () => ({ req }), // контекст теперь принимает Request напрямую
  });

export { handler as GET, handler as POST };

5. Поддержка FormData и File Upload

v11 добавляет нативную поддержку загрузки файлов через FormData в процедурах:

// server: принимаем файл
uploadAvatar: protectedProcedure
  .input(z.instanceof(FormData))
  .mutation(async ({ input, ctx }) => {
    const file = input.get('file') as File;
    // обрабатываем файл...
    return { url: '/uploads/' + file.name };
  }),

6. Типы контекста и middleware

В v11 уточнены generic-типы middleware. Тип возвращаемого значения next() теперь строже типизирован — код с неявным any в middleware может начать выдавать ошибки типов при миграции.

Breaking Changes при миграции с v10

  • Переместить transformer из корневого конфига клиента в каждый link
  • Заменить createTRPCProxyClient на createTRPCClient
  • Проверить типы middleware — могут появиться новые ошибки TypeScript
  • Обновить @trpc/server, @trpc/client, @trpc/react-query одновременно — версии должны совпадать

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

  • Обновление только одного пакета из группы (@trpc/server без @trpc/client) приводит к ошибкам типов и рантайм-несовместимости — обновляйте все пакеты tRPC вместе.
  • SSE через httpSubscriptionLink не работает в браузерах без поддержки EventSource — проверьте совместимость с вашей целевой аудиторией (IE11 не поддерживает).
  • При переносе трансформера в link нужно обновить и серверную, и клиентскую конфигурацию одновременно — промежуточное состояние приведёт к битой сериализации.
  • Changelog v11 содержит экспериментальные API (помечены unstable_) — не используйте их в продакшене, интерфейс может измениться в патч-версии.
  • Если проект использует кастомные links, нужно проверить совместимость observable-API — внутренние типы обновились.
  • FormData upload требует настройки CSRF-защиты отдельно — tRPC не добавляет её автоматически.
  • Документация v11 в период выхода была неполной — опирайтесь на changelog и issues в GitHub репозитории trpc/trpc для актуальных примеров.

Common mistakes

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

What the interviewer is testing

  • Объясняет миграция версии, обновление пакетов и изменения integration surface.
  • Показывает на примере, как работает: v11 требует сверяться с migration guide, особенно для React Query integration, server adapters, links и unstable/internal imports; нельзя переносить v10 snippets без проверки текущих docs.
  • Называет production-нюанс и граничный случай для темы «tRPC v11 и v10».

Sources

Related topics