يا جماعة الخير، السلام عليكم ورحمة الله.
اسمحولي اليوم أحكيلكم قصة صارت معي قبل كم سنة، قصة علّمتني درس كبير في عالم تطوير البرمجيات. وقتها كنت شغال أنا وفريقي على تطبيق موبايل لشبكة اجتماعية جديدة. كنا متحمسين كثير، ليالي وأيام واحنا بنشتغل، الكود شغال زي الحلاوة على أجهزتنا السريعة وإنترنت الشركة الصاروخي.
يوم الإطلاق التجريبي، وزعنا التطبيق على مجموعة مستخدمين… وهنا بدأت المأساة. الشكاوى بلشت توصل: “التطبيق بطيء جداً”، “بياكل كل باقة الإنترنت”، “الصفحة الرئيسية بتضل تحمل للأبد”.
أنا وفريقي حطينا راسنا براس بعض، مش فاهمين شو اللي بصير. قعدت أمسك التطبيق وأحلل الشبكة (Network analysis)، وفتحت الـ Log… وهنا كانت الصدمة. اكتشفت إنه عشان نحمّل الصفحة الشخصية للمستخدم، اللي هي بتحتاج بس اسمه وصورته وكم معلومة بسيطة، الـ API تبعنا كان يرجع ملف JSON حجمه ٢ ميجابايت! 😱
كان طلب الـ API الواحد لـ /api/user/123 بيرجع كل تاريخ حياة المستخدم: كل بوستاته، كل تعليقاته، كل أصدقائه، إعداداته الخاصة، سجل مشترياته… باختصار، كان بيرجع “بيانات الكون كله” زي ما بحكي العنوان. قعدت صافن في الشاشة وبحكي لحالي: “يا زلمة، شو هاد؟ ليش كل هاي البيانات عشان نعرض سطرين؟”.
هذا الجحيم اللي كنا عايشين فيه اسمه تقنياً “Over-fetching”، وكان هو السبب في قتل أداء تطبيقنا. ومن هنا بدأت رحلتنا للبحث عن حل، رحلة انتهت بحب من أول نظرة مع تقنية اسمها GraphQL.
جحيم واجهات برمجة التطبيقات التقليدية (REST API)
قبل ما نحكي عن المنقذ GraphQL، خلينا نفهم أصل المشكلة اللي كنا فيها. أغلبنا بيشتغل مع REST APIs، وهي طريقة ممتازة ومنظمة لتبادل البيانات. لكن مع تعقيد التطبيقات الحديثة، ظهرت عيوبها بوضوح.
المشكلة الأولى: الجلب الزائد (Over-fetching)
زي ما صار معنا بالضبط. أنت بتطلب معلومة صغيرة، لكن الخادم (Server) مصمم يرجعلك كل المعلومات المتعلقة بهذا الطلب في “قالب” ثابت. تخيل أنك تريد فقط اسم المستخدم من نقطة النهاية (Endpoint) التالية /api/users/1، ولكنك تحصل على هذا:
{
"id": 1,
"name": "أبو عمر",
"username": "abu_omar_dev",
"email": "email@example.com",
"address": {
"street": "شارع يافا",
"city": "القدس",
"zipcode": "91000"
},
"phone": "1-770-736-8031",
"website": "abuomar.dev",
"company": {
"name": "شركة البرمجة المتقدمة",
"catchPhrase": "نحو كود نظيف"
},
// ... والكثير الكثير من البيانات الأخرى
}
تطبيق الموبايل كان يحتاج فقط لـ name، ولكنه استقبل كل هذه البيانات واضطر يحللها. هذا استنزاف للشبكة، للبطارية، ولصبر المستخدم.
المشكلة الثانية: الجلب الناقص والطلبات المتعددة (Under-fetching & N+1 Problem)
هذه هي الوجه الآخر للعملة. أحيانًا، لا تكفي نقطة نهاية واحدة. تخيل أنك تريد عرض صفحة مؤلف مع آخر 3 مقالات له. باستخدام REST، ستحتاج على الأغلب لعمل التالي:
- الطلب الأول: جلب بيانات المؤلف من
/api/users/1. - الطلب الثاني: جلب مقالات هذا المؤلف من
/api/users/1/posts.
هذا يسمى Under-fetching، حيث لم تحصل على كل ما تحتاجه من طلب واحد. هذا يؤدي إلى سلسلة من الطلبات المتتالية (Request waterfalls) التي تبطئ تحميل الواجهة. المشكلة تتعقد أكثر عندما تحتاج لبيانات مرتبطة بالبيانات المرتبطة (مثلاً، التعليقات على كل مقال)، وهذا ما يعرف بمشكلة “N+1”.
مرحباً بـ GraphQL: لغة الاستعلام التي تطلبها بنفسك
القصة وما فيها، GraphQL هي لغة استعلام (Query Language) لواجهات برمجة التطبيقات، تم تطويرها في فيسبوك عام 2012 لحل هذه المشاكل بالضبط. الفكرة عبقرية في بساطتها: بدلًا من أن يقرر الخادم ما هي البيانات التي سيرسلها، يقوم العميل (Client) بتحديد البيانات التي يحتاجها بالضبط.
لا أكثر ولا أقل. أنت تطلب ما تريد، وتحصل على ما طلبت.
كيف يعمل هذا السحر؟ لنقارن بين REST و GraphQL
لنفترض نفس السيناريو: نريد اسم المؤلف وعناوين آخر 3 مقالات له.
الطريقة التقليدية (REST)
كما ذكرنا، ستحتاج على الأقل لطلبين:
GET /api/users/1GET /api/users/1/posts?limit=3
وهذا يسبب تأخيرًا ملحوظًا في تحميل الصفحة.
طريقة GraphQL السحرية
مع GraphQL، كل التطبيق يتحدث مع نقطة نهاية واحدة فقط (عادة /graphql). أنت ترسل طلبًا واحدًا (Query) يصف تمامًا البيانات التي تريدها، بهذا الشكل:
query GetAuthorWithPosts {
user(id: "1") {
name
posts(last: 3) {
title
}
}
}
والأجمل من ذلك، هو شكل الرد الذي ستحصل عليه. سيكون مطابقًا تمامًا لشكل طلبك:
{
"data": {
"user": {
"name": "أبو عمر",
"posts": [
{ "title": "لماذا نستخدم Next.js؟" },
{ "title": "مقدمة إلى Docker" },
{ "title": "دليلك الشامل لـ TypeScript" }
]
}
}
}
لاحظ الجمال: طلب واحد، نقطة نهاية واحدة، وحصلت بالضبط على ما أريد، لا بايت واحد زيادة. هذا هو التغيير الجذري الذي أنقذ تطبيقنا وأعاد البسمة لوجوه المستخدمين.
أبو عمر، كيف أبدأ مع GraphQL؟
سؤال ممتاز. البداية قد تبدو صعبة، لكنها أسهل مما تتوقع. GraphQL يتكون من جزأين رئيسيين: الخادم والعميل.
على جهة الخادم (Backend)
هنا تقوم بتعريف “مخطط” (Schema) البيانات الخاصة بك. هذا المخطط هو العقد بينك وبين مطوري الواجهات الأمامية، يصف كل البيانات المتاحة وكيفية طلبها.
المكونات الأساسية للمخطط:
- Types: تصف أنواع الكائنات في نظامك (مثل
User,Post,Comment). - Queries: تصف الطرق المتاحة لجلب البيانات (عمليات القراءة).
- Mutations: تصف الطرق المتاحة لتعديل البيانات (عمليات الإنشاء، التحديث، الحذف).
مثال بسيط لمخطط (Schema)
هذا مثال بسيط بلغة تعريف المخطط (SDL) لتطبيق مدونة:
# يصف كائن المقال
type Post {
id: ID!
title: String!
content: String
author: User!
}
# يصف كائن المستخدم
type User {
id: ID!
name: String!
email: String!
posts: [Post!]
}
# نقطة الدخول لجلب البيانات
type Query {
# جلب كل المقالات
allPosts: [Post!]
# جلب مقال محدد بالـ ID
postById(id: ID!): Post
# جلب مستخدم محدد بالـ ID
userById(id: ID!): User
}
بعد تعريف المخطط، تستخدم مكتبة مثل Apollo Server (لـ Node.js) أو Graphene (لـ Python) لربط هذا المخطط مع دوال (Resolvers) تجلب البيانات الفعلية من قاعدة البيانات.
على جهة العميل (Frontend)
الوضع أسهل بكثير. يمكنك استخدام مكتبة عميل مثل Apollo Client أو Relay. هذه المكتبات تسهل عملية إرسال الـ Queries والـ Mutations، وتوفر ميزات رائعة مثل التخزين المؤقت (Caching) وإدارة الحالة (State Management) تلقائيًا.
ببساطة، تكتب استعلامك في الواجهة الأمامية، والمكتبة تتكفل بالباقي.
نصائح من “الختيار”: متى تختار GraphQL؟
من خبرتي، GraphQL ليس حلًا سحريًا لكل المشاكل، هو أداة قوية جدًا في “صندوق العدة” تبعك، ولكن يجب أن تعرف متى تستخدمها.
نصيحة عملية: قبل أن تقرر استخدام GraphQL، اسأل نفسك: هل أعاني حقًا من مشاكل الـ Over-fetching أو الـ Under-fetching؟ هل لدي عدة عملاء (ويب، موبايل، iOS) يحتاجون بيانات مختلفة من نفس المصدر؟
- ✅ استخدم GraphQL إذا:
- تطبيقك يحتوي على واجهات معقدة تحتاج بيانات من مصادر متعددة (مثل فيسبوك).
- تطور تطبيقات موبايل حيث كل بايت من البيانات يهم.
- لديك فرق متعددة (Frontend, Backend, Mobile) وتحتاج لعقد قوي (Schema) بينها.
- تريد تطوير الـ API الخاص بك بسرعة بدون الحاجة لعمل إصدارات (v1, v2, v3).
- ❌ فكر مرتين قبل استخدام GraphQL إذا:
- الـ API الخاص بك بسيط جدًا (مثلاً، Microservice يؤدي وظيفة واحدة).
- فريقك ليس لديه الوقت لتعلم التقنية الجديدة والمنحنى التعليمي الخاص بها.
- مشروعك بسيط جدًا لدرجة أن REST API التقليدي يفي بالغرض وزيادة.
الخلاصة: هل هي النهاية لـ REST؟
بالتأكيد لا. REST API ما زالت قوية ومفيدة جدًا في الكثير من الحالات، خصوصًا في الخدمات المصغرة (Microservices) والـ APIs البسيطة.
لكن GraphQL قدمت حلاً ثوريًا لمشاكل حقيقية كانت تواجه المطورين في التطبيقات الحديثة والمعقدة. لقد حررت مطوري الواجهات الأمامية من الاعتماد الكامل على فريق الواجهات الخلفية لتصميم الـ Endpoints، ومنحتهم القوة لطلب ما يريدون بالضبط.
نصيحتي الأخيرة لك: لا تخف من التجربة. ابدأ بمشروع جانبي صغير، أو حتى جزء صغير من مشروعك الحالي. قم ببناء خادم GraphQL بسيط فوق قاعدة بيانات موجودة، وجرب أن تطلب منه البيانات من واجهة أمامية. شاهد بنفسك الفرق في الأداء والمرونة.
قد تكون GraphQL هي الأداة التي كانت ناقصاك لتنقل مشاريعك إلى مستوى آخر من الكفاءة والسرعة. بالتوفيق يا جماعة الخير! 🚀