أمضى أحد المطورين أسبوعين في استبدال REST API بـ tRPC في أداة داخلية.
لماذا كان هذا التحول مهماً
أجبرتنا البنية التقنية القديمة على صيانة DTO، وأداة تحقق (validator)، ومجموعة منفصلة من أنواع TypeScript للواجهة الأمامية. إذا قمت بتغيير اسم حقل في الخلفية (backend)، فسيظل الـ API يعيد استجابة 200، وستستمر واجهة المستخدم في العرض، ولن يظهر الخطأ إلا في شكل قيم "undefined". لقد اكتشف أحد العملاء المشكلة قبل أي شخص في الفريق. كانت عقود REST تخفي المشكلة، وأضافت الملفات الإضافية عبء صيانة لم يأتِ بأي نتيجة.
كيف كان يبدو إعداد REST
- OpenAPI spec – ملف ثابت يصف نقاط النهاية (endpoints) ولكنه لم يكن يعمل أبداً كمصدر وحيد للحقيقة (source of truth).
- خطوة توليد Client SDK – مهمة في التكامل المستمر (CI) كانت تنتج غلافاً (wrapper) بلغة JavaScript.
- مجموعة Postman – ملف اختبار مشترك لم يستخدمه أحد.
- واجهات TypeScript يدوية – أنواع مكتوبة يدوياً كان يجب أن تظل متزامنة مع الخادم.
كل تغيير في الـ API كان يؤثر على ثلاثة على الأقل من هذه الملفات، بالإضافة إلى أداة التحقق وأي استدعاءات fetch تابعة لها. كانت العملية عرضة للأخطاء وبطيئة.
كيف قلص tRPC حجم الكود المصدري
يلغي tRPC ملف العقد المنفصل. يقوم الخادم بتصدير نوع الراوتر (router type)؛ ويقوم العميل باستيراد نفس هذا النوع. إذا قمت بتغيير اسم حقل في الخلفية، فسيقوم المحرر بتنبيهك إلى عدم التطابق فوراً — دون الحاجة لتشغيل الكود أو انتظار فشل الطلب. قام المطور بإزالة:
- ملف OpenAPI spec.
- خطوة توليد client SDK.
- مجموعة Postman غير المستخدمة.
- مجلد واجهات TypeScript اليدوية.
أصبح المستودع (repo) أكثر رشاقة، ووصلت الملاحظات أثناء عملية التطوير بدلاً من مرحلة النشر.
حدود tRPC
يعمل tRPC فقط عندما يتحدث الطرفان لغة TypeScript. ولكنه يقصر في الحالات التالية:
- إذا كان فريق تطبيقات الهاتف يستخدم Swift أو Kotlin.
- إذا كان يجب استهلاك الـ API من قبل شركاء خارجيين.
- إذا كنت بحاجة إلى واجهة عامة ومستقلة عن لغة البرمجة (language-agnostic).
ما تطلبه الانتقال فعلياً
كان الجهد الذي استغرق أسبوعين أكثر من مجرد نسخ ولصق. كان على المطور القيام بما يلي:
- إعادة كتابة كل استدعاء
fetchلاستخدام وظائف عميل tRPC. - تعديل منطق معالجة الأخطاء.
- تحديث مكونات واجهة المستخدم التي كانت تعتمد على حالات التحميل وإعادة المحاولة المرتبطة باستجابات HTTP الخام.
أسئلة يجب طرحها قبل البدء
- هل يستخدم كل من الواجهة الأمامية والخلفية لغة TypeScript؟ بدون نظام أنواع مشترك، يفقد tRPC ميزته الرئيسية.
- هل الفريق نفسه مسؤول عن كلا الجانبين؟ يمكن لفجوات الملكية أن تعيد مشكلة عدم تطابق العقود (contract drift).
- هل تقوم بإصلاح خطأ ملموس أم تتبع مجرد صيحة تقنية؟ تعزيز الإنتاجية حقيقي، ولكن يجب أن يحل مشكلة قائمة بالفعل.
نهج هجين لعام 2025
تجد العديد من الفرق الحل الأمثل من خلال تشغيل كلا البنيتين:
- tRPC لطبقات التطبيقات الداخلية حيث يكون الكود المصدري بالكامل بلغة TypeScript ويمتلك نفس الفريق الخادم والعميل.
- REST للـ webhooks، والـ APIs العامة، وتكاملات الشركاء حيث يتطلب الأمر وصولاً مستقلاً عن لغة البرمجة.
إن استخدام الأداة المناسبة لكل واجهة يحافظ على سرعة التطوير الداخلي مع الحفاظ على الانفتاح المطلوب للمستهلكين الخارجيين.
الخلاصة: يمكن لاستبدال REST بـ tRPC أن يلغي تكرار ملفات العقود ويظهر الأخطاء أثناء وقت التحرير، ولكن المكاسب لا تتحقق إلا عندما تشترك البنية التقنية بالكامل في TypeScript وتستطيع الفرق استيعاب تكلفة الانتقال. تتيح لك الاستراتيجية المختلطة جني الفوائد دون استبعاد المستهلكين الذين لا يستخدمون TypeScript.
