tRPC
End-to-end type safety bez code generation — pełny stack TypeScript od serwera po klienta, integracja z Next.js i TanStack Query.
tRPC vs alternatywy type-safe API
tRPC, GraphQL, REST, Zodios, oRPC i Hono RPC — każde rozwiązanie optymalizuje inny aspekt type safety, protokołu i kompatybilności klientów.
| Technologia | Type Safety | Code Gen | Protokół | Klienci | Kiedy |
|---|---|---|---|---|---|
| tRPC | End-to-end (compile time) | Nie | HTTP RPC | Tylko TypeScript | Full-stack TS monorepo, Next.js |
| GraphQL + codegen | Generowane typy | Tak (schema -> typy) | GraphQL | Dowolny | Złożone dane, wielu klientów |
| REST + OpenAPI | Generowane typy (opcjonalne) | Opcjonalne | HTTP REST | Dowolny | Publiczne API, zewnętrzni klienci |
| Zodios | Client-side (Zod) | Nie | HTTP REST | Dowolny (schema exportable) | Typowany klient dla istniejącego REST |
| oRPC | End-to-end + OpenAPI | Nie (generuje schema) | HTTP RPC + REST | TS + REST clients | tRPC + zewnętrzni klienci |
| Hono RPC | End-to-end | Nie | HTTP | Tylko TypeScript | Hono framework, edge deployment |
Często zadawane pytania
Co to jest tRPC i dlaczego jest popularne w ekosystemie TypeScript?
tRPC (TypeScript Remote Procedure Call): biblioteka do budowania end-to-end type-safe API bez generowania kodu. Kluczowa idea: serwer i klient współdzielą typy TypeScript. Żadnego code generation (jak GraphQL codegen). Żadnego schema validation w dwóch miejscach (serwer + klient). Jak działa: serwer definiuje procedury (query/mutation) z typami. Klient importuje typy serwera. TypeScript weryfikuje poprawność w compile time. Przykład serwer: export const appRouter = router({getUser: publicProcedure.input(z.object({id: z.string()})).query(async ({input}) => {return db.user.findById(input.id)})}). Klient: const user = await trpc.getUser.query({id: '123'}). TypeScript wie że user ma typ User — bez żadnego schematu JSON. Zalety tRPC: zero boilerplate dla typowania API. Refactoring: zmień typ na serwerze -> TypeScript błędy na kliencie natychmiast. Autouzupełnianie po procedurach API. Brak over/under-fetching (procedura zwraca dokładnie to co potrzeba). Wady tRPC: tylko TypeScript. Nie działa dla non-TypeScript klientów. Brak standardowego protokołu (nie REST, nie GraphQL). Trudniejsze do mockowania. Stack: T3 Stack (create-t3-app) — Next.js + tRPC + Prisma + Tailwind + NextAuth.
tRPC — router, procedure, middleware i context?
Router: grupuje procedury. export const appRouter = router({users: userRouter, posts: postRouter}). Nested routers: userRouter.list, userRouter.getById, userRouter.create. Procedure: funkcja API. query — odczyt (GET). mutation — zapis (POST/PUT/DELETE). subscription — real-time (WebSocket). Input validation z Zod: .input(z.object({id: z.string().uuid()})). .input(z.string().min(1).max(100)). TypeScript infer z Zod schematu. Automatyczna walidacja na serwerze. Context: współdzielony obiekt dostępny w każdej procedurze. Sesja użytkownika, połączenie DB, logger. createContext: ({req, res}) => ({session: getSession(req), db, logger}). Middleware: .use(async ({ctx, next}) => {if (!ctx.session) throw new TRPCError({code: 'UNAUTHORIZED'}). return next({ctx: {...ctx, user: ctx.session.user}})}). publicProcedure — brak autentykacji. protectedProcedure — wymaga zalogowania. adminProcedure — wymaga roli admin. Error handling: TRPCError({code: 'NOT_FOUND', message: 'User not found'}). Kody: BAD_REQUEST, UNAUTHORIZED, FORBIDDEN, NOT_FOUND, INTERNAL_SERVER_ERROR. Automatyczna serializacja błędów do klienta. Input + Output transformation: .transformer(SuperJSON) — obsługa Date, Map, Set, undefined.
tRPC z Next.js i TanStack Query — integracja?
tRPC + Next.js App Router: API route handler: app/api/trpc/[trpc]/route.ts. fetchRequestHandler. tRPC + TanStack Query (@trpc/react-query): automatycznie generuje useQuery/useMutation hooki per procedura. const trpc = createTRPCReact(). const utils = trpc.useUtils(). Użycie: const {data: users, isLoading} = trpc.users.list.useQuery({page: 1}). Dokładnie jak useQuery ale z autouzupełnianiem. Mutation: const createUser = trpc.users.create.useMutation({onSuccess: () => utils.users.list.invalidate()}). Cache invalidation przez utils. Prefetching w Server Components (Next.js app router): const trpc = createTRPCProxyClient({links: [...]}). await trpc.users.list.query(). Hydrate client z tymi danymi. Subscriptions z WebSocket: trpc.notification.onNew.useSubscription(). Require WebSocket link zamiast HTTP link. Links: httpBatchLink — batch wiele calls w jeden HTTP request. splitLink — różne transport per typ. wsLink — WebSocket dla subskrypcji. loggerLink — logowanie. Batch requests: domyślnie wiele trpc calls w jednym renderze -> jeden HTTP request. Konfiguracja batch delay. Optymalizacja: deduplikacja identycznych queries (jak TanStack Query). Cache per procedura+input. SuperJSON: tRPC używa SuperJSON do serializacji. Date, undefined, Map, Set prawidłowo serialized.
tRPC vs REST vs GraphQL — kiedy co wybrać?
REST API: standardowy protokół. Działa z każdym klientem (mobile, web, zewnętrzni partnerzy). OpenAPI spec. Rate limiting, versioning standardowe. Wady: boilerplate typowania. Ręczna synchronizacja typów klient-serwer. Over/under-fetching. GraphQL: elastyczne queries (pobierz tylko potrzebne pola). Schema jako kontrakt. Doskonałe dla złożonych, zagnieżdżonych danych. Persisted queries, DataLoader (batching). Wady: learning curve. Kompleksowa konfiguracja. Code generation dla type safety. tRPC: end-to-end type safety bez code gen. Tylko TypeScript. Idealne dla full-stack TypeScript monorepo. Wady: tylko dla TypeScript klientów. Brak standardowego protokołu. Trudniejsze external integrations. Decision matrix: zewnętrzni klienci / publiczne API -> REST z OpenAPI. Mobilna aplikacja + web -> REST lub GraphQL. Złożone zagnieżdżone dane, social graph -> GraphQL. Full-stack TypeScript (Next.js, SvelteKit) -> tRPC. Wewnętrzne API gdzie wszyscy to TypeScript -> tRPC. Kiedy tRPC jest idealne: T3 Stack. Fullstack Next.js monorepo. Startup gdzie wszyscy devs = TypeScript. Brak zewnętrznych klientów. Kiedy nie używaj tRPC: mobile apps (React Native ok, ale native iOS/Android nie). Zewnętrzni partnerzy API. Mikrousługi z różnymi językami. Publiczne API.
Alternatywy dla tRPC — Hono RPC, Elysia Eden, oRPC, Zodios?
tRPC nie jest jedyną opcją dla type-safe API. Hono RPC: Hono framework + RPC client. client() z typami. Działa z Hono routes. Elysia + Eden: Elysia (Bun-native framework) + Eden client. Podobne DX do tRPC. Zoptymalizowane dla Bun. oRPC: nowy challanger tRPC. Kompatybilny z OpenAPI. Eksportuje schema do JSON. Zewnętrzni klienci mogą używać REST. Zodios: Axios + Zod typings. Client-side: zdefiniuj API schema Zod. zodios(baseUrl, apiDefinition). type-safe axios. Działa dla istniejących REST API. ts-rest: typowany kontrakt dla REST API. Działa jak adapter nad istniejącym REST. Możesz wygenerować OpenAPI. GraphQL Code Generator: klasyczny approach. Schema GraphQL -> typy TypeScript + hooki. Apollo, URQL, Relay. Duży ekosystem, dojrzały. Next-Safe-Action: Server Actions z type safety i Zod validation. Bez tRPC dla prostszych przypadków. Wybór frameworka 2024: T3 Stack -> tRPC. SvelteKit -> tRPC lub Zodios. Bun + Elysia -> Eden. Hono -> Hono RPC. REST existing API -> Zodios lub ts-rest. Nowe full-stack TS project -> tRPC lub oRPC (jeśli OpenAPI ważny).
Powiązane artykuły
Skontaktuj się z nami
Porozmawiajmy o Twoim projekcie. Bezpłatna wycena w ciągu 24 godzin.
Wyślij zapytanie
Telefon
+48 790 814 814
Pon-Pt: 9:00 - 18:00
adam@fotz.pl
Odpowiadamy w ciągu 24h
Adres
Plac Wolności 16
61-739 Poznań
Godziny pracy
Wolisz porozmawiać?
Zadzwoń teraz i porozmawiaj z naszym specjalistą o Twoim projekcie.
Zadzwoń teraz