almessadi.
Retour à l'index

tRPC est meilleur lorsque l'ensemble de la pile parle déjà TypeScript_

tRPC supprime beaucoup de duplication d'API dans les systèmes full-stack TypeScript, mais il brille uniquement lorsque les frontières architecturales sont déjà proches.

Publié28 juillet 2024
Temps de lecture8 min read

tRPC est loué comme s'il remplaçait tous les styles d'API. Ce n'est pas le cas.

Ce qu'il fait très bien, c'est supprimer le travail de coordination inutile à l'intérieur d'une pile TypeScript étroitement couplée. Si votre frontend et votre backend vivent déjà près l'un de l'autre, et que les deux sont écrits en TypeScript, tRPC peut réduire la duplicité des saisies et la dérive des interfaces.

C'est un véritable avantage. Ce n'est tout simplement pas universel.

Le Problème Qu'il Résout

Dans de nombreuses applications full-stack TypeScript, le même contrat est décrit trois fois :

  • validation des entrées
  • types des gestionnaires backend
  • types des consommateurs frontend

Cette duplication est l'endroit où des bogues et des hypothèses obsolètes s'infiltrent.

tRPC réduit une grande partie de cela en permettant au client d'inférer les types de procédures directement depuis le routeur du serveur :

import { initTRPC } from "@trpc/server";
import { z } from "zod";

const t = initTRPC.create();

export const appRouter = t.router({
  getUser: t.procedure
    .input(z.object({ id: z.string() }))
    .query(async ({ input }) => {
      return db.user.findById(input.id);
    }),
});

export type AppRouter = typeof appRouter;

Du côté client, vous n'avez plus besoin de maintenir une seconde version du contrat :

import { createTRPCProxyClient, httpBatchLink } from "@trpc/client";
import type { AppRouter } from "./server";

const trpc = createTRPCProxyClient<AppRouter>({
  links: [httpBatchLink({ url: "/api/trpc" })],
});

const user = await trpc.getUser.query({ id: "123" });

C'est la partie que les gens apprécient : moins de coutures manuscrites.

Pourquoi C'est Si Agréable

tRPC est excellent lorsque :

  • l'application est un monorepo ou un équivalent proche
  • TypeScript est le langage des deux côtés
  • le frontend n'est pas censé être un large consommateur d'API public

Dans ce contexte, vous obtenez une boucle de feedback très rapide. Renommez un champ sur le serveur, et le client se casse généralement à la compilation au lieu d'une semaine plus tard lors de l'assurance qualité.

Les Compromis

tRPC est moins efficace lorsque :

  • plusieurs langages doivent consommer l'API
  • l'API est publique ou destinée aux partenaires
  • le backend et le frontend évoluent indépendamment
  • les contrats au niveau du protocole comptent plus que la commodité de l'inférence de type

C'est là que REST ou gRPC ont généralement plus de sens. Pas parce qu'ils sont plus modernes, mais parce qu'ils sont plus découplés.

Un Meilleur Cadre

tRPC n'est pas "la mort de REST."

C'est un très bon choix pour une catégorie spécifique d'équipe produit :

  • une organisation
  • une pile
  • un système de types partagé

Si c'est votre situation, c'est une option solide.

Si ce n'est pas le cas, forcer tRPC dans l'architecture crée généralement un autre type de problème de couplage.

Lectures Complémentaires