tRPC مقابل REST
tRPC (واجهة RPC آمنة النوع، لـ TypeScript الشاملة) في مواجهة REST API (محايدة اللغة، معيارية) — مقارنة بين أساليب تصميم واجهات البرمجة. الأمان النوعي، نظام الأدوات، وقابلية التوسع.
صفر codegen، أمان نوع TypeScript من طرف إلى طرف
لغة استعلام عالمية تعتمد على المخطط أولًا لعملاء متعددين
اتخذ القرار حسب الحالة؛ فـ'أمان النوع' وحده ليس مبررًا لاختيار GraphQL. إذا كنت تستخدم monorepo واحدًا بلغة TypeScript وعميل ويب واحدًا، فإن tRPC يقلّل العمل تقريبًا دائمًا — صفر codegen، وأي تغيير في الخادم يظهر فورًا كخطأ TypeScript في العميل. إذا كان لديك تطبيق جوال، أو واجهة API عامة مفتوحة للمطوّرين الخارجيين، أو حاجة إلى فدرالية متعددة الفرق، فإن عقد المخطط المستقل عن اللغة في GraphQL ونظام Apollo Federation البيئي يوفران ميزة بنيوية.
| الفئة | tRPC | GraphQL |
|---|---|---|
| الأداء | 7/10 | 6/10 |
| سهولة التعلّم | 8/10 | 5/10 |
| النظام البيئي | 6/10 | 9/10 |
| المجتمع | 7/10 | 8/10 |
| سوق العمل | 5/10 | 8/10 |
| الاستدامة المستقبلية | 7/10 | 8/10 |
// tRPC — تعريف الموجّه (router) في الخادم
import { initTRPC } from '@trpc/server';
import { z } from 'zod';
// db = عميل Prisma/ORM (يُستورد من ملف منفصل)
const t = initTRPC.create();
export const appRouter = t.router({
getUser: t.procedure
.input(z.object({ id: z.string() }))
.query(async ({ input }) => {
return db.user.findUnique({ where: { id: input.id } });
}),
});
export type AppRouter = typeof appRouter;
// العميل — نوع الخادم يُستنتج تلقائيًا، لا يوجد codegen
import { createTRPCClient, httpBatchLink } from '@trpc/client';
import type { AppRouter } from './server';
const client = createTRPCClient<AppRouter>({
links: [httpBatchLink({ url: 'http://localhost:3000/trpc' })],
});
const user = await client.getUser.query({ id: '1' });
// user: { id: string; name: string; ... } — أمان نوع كامل وقت الترجمة (compile-time)// graphql-js + @apollo/server — المخطط وresolver والخادم في ملف واحد
import { ApolloServer } from '@apollo/server';
import { startStandaloneServer } from '@apollo/server/standalone';
// db = عميل Prisma/ORM (يُستورد من ملف منفصل)
const typeDefs = `#graphql
type Post {
id: ID!
title: String!
}
type User {
id: ID!
name: String!
posts: [Post!]!
}
type Query {
user(id: ID!): User
}
`;
const resolvers = {
Query: {
user: (_parent, { id }, { db }) => db.user.findUnique({ where: { id } }),
},
User: {
posts: (user, _args, { db }) =>
db.post.findMany({ where: { authorId: user.id } }),
},
};
const server = new ApolloServer({ typeDefs, resolvers });
const { url } = await startStandaloneServer(server, {
context: async () => ({ db }),
listen: { port: 4000 },
});
console.log(`الخادم جاهز: ${url}`);
// استعلام العميل — تُختار الحقول المطلوبة فقط:
// query { user(id: "1") { name posts { title } } }اتخذ القرار حسب الحالة؛ فـ'أمان النوع' وحده ليس مبررًا لاختيار GraphQL. إذا كنت تستخدم monorepo واحدًا بلغة TypeScript وعميل ويب واحدًا، فإن tRPC يقلّل العمل تقريبًا دائمًا — صفر codegen، وأي تغيير في الخادم يظهر فورًا كخطأ TypeScript في العميل. إذا كان لديك تطبيق جوال، أو واجهة API عامة مفتوحة للمطوّرين الخارجيين، أو حاجة إلى فدرالية متعددة الفرق، فإن عقد المخطط المستقل عن اللغة في GraphQL ونظام Apollo Federation البيئي يوفران ميزة بنيوية.
احصل على استشارة مجانيةإذا كنت تعمل بـ monorepo واحد بلغة TypeScript وعميل ويب واحد، فإن tRPC يتطلب كودًا وإعدادات أقل (صفر codegen، واستنتاج TS من طرف إلى طرف — trpc.io). إذا كان لديك تطبيق جوال، أو واجهة API عامة مفتوحة للمطوّرين الخارجيين، أو عدة خدمات مستقلة، فإن عقد المخطط ونظام الفدرالية البيئي (Apollo Federation) في GraphQL يوفران تجريدًا أنسب.