I'm always excited to take on new projects and collaborate with innovative minds.

Phone

+20 115 052 9992

Website

https://ibrahimahmed.online/

Social Links

بناء نظام إشعارات يعتمد على Server-Sent Events (SSE) كبديل للـ WebSockets

يا هلا بيك يا بشمهندس في مقال تقني جديد. خلينا نبدأ كلامنا بسؤال واقعي: كم مرة طلبت منك إدارة المنتج أو الـ Product Manager تعمل نظام إشعارات لحظية (Real-time N

بناء نظام إشعارات يعتمد على Server-Sent Events (SSE) كبديل للـ WebSockets
Reading Count: 6

يا هلا بيك يا بشمهندس في مقال تقني جديد. خلينا نبدأ كلامنا بسؤال واقعي: كم مرة طلبت منك إدارة المنتج أو الـ Product Manager تعمل نظام إشعارات لحظية (Real-time Notifications) في الموقع بتاعك؟ وأول حاجة جت في دماغك إيه؟ بنسبة كبيرة جداً، قلت لنفسك: "يلا بينا نعمل WebSockets".

طيب، كمل معايا القصة دي... بدأت تكتب كود الـ WebSocket، وعملت اتصال ثنائي الاتجاه (Bi-directional Connection)، وظبطت الـ Handshake، وكل حاجة اشتלت تمام. بس بعد ما الموقع طلع الـ Production، لاحظت إن السيرفر بيستهلك رامات (RAM) وبورسيسور (CPU) أكتر بكتير من المعتاد، ده غير إن الاتصال أحياناً بيقع وتحتاج تعمل إعادة اتصال (Reconnection) بنفسك، والموضوع طلع معقد جداً على حاجة بسيطة زي: السيرفر عايز يقول للمتصفح "فيه إشعار جديد يا معلم"، ومن غير ما المتصفح يرد عليه أصلاً!

لو حسيت بالوجع ده قبل كده، فالمقال ده معمول عشانك. هنتكلم النهارده عن بديل عبقري، خفيف، وسهل جداً، وهو تدفق البيانات من السيرفر للمتصفح (Server-Sent Events) أو باختصار SSE.

إيه هو الـ Server-Sent Events (SSE) ومنين بيطلع؟

ببساطة شديدة، الـ Server-Sent Events (SSE) هي تقنية ويب بتسمح للسيرفر إنه يبعث تحديثات للـ Browser في اتجاه واحد (Unidirectional Flow). يعني الاتصال بيمشي في خط مستقيم من السيرفر (Server) للمتصفح (Client)، ومن غير ما المتصفح يضطر يبعث طلبات كل شوية (Polling) أو يفتح قناة اتصال معقدة زي الـ WebSockets.

الموضوع بيشتغل فوق بروتوكول الـ HTTP العادي جداً (HTTP Protocol). المتصفح بيفتح اتصال باستخدام كلاس جافاسكريبت اسمه EventSource، والسيرفر بيثبت الاتصال ده المفتوح (Keep-Alive)، وكل ما يحصل حدث جديد (Event)، يقوم السيرفر دايس "بوش" للبيانات دي في شكل نصي (Plain Text) بالنسق المخصص للـ SSE.

ليه تختار الـ SSE وتطنش الـ WebSockets في الإشعارات؟

علشان تاخد قرار صح كمبرمج شاطر، لازم تعرف إيه المميزات والعيوب. الـ WebSockets تقنية عظيمة جداً، بس مخصصة لحاجة تانية خالص زي ألعاب الشات (Chat Applications) أو الألعاب الجماعية (Multiplayer Games) اللي بتحتاج تبادل بيانات سريع وفي الاتجاهين في نفس اللحظة.

لكن لو مشروعك عبارة عن نظام إشعارات (Notifications)، لوحة تحكم (Dashboard) بتعرض أسهم، أو أخبار بتحدث نفسها بنفسها، فالـ SSE بيكسب بجدارة للأسباب دي:

  • سهولة الاستخدام (Simplicity): الـ SSE بيشتغل على بروتوكول HTTP العادي، مش محتاج سيرفرات خاصة أو إعدادات معقدة زي الـ WebSockets.
  • إعادة الاتصال التلقائي (Auto-Reconnection): دي ميزة خارقة في الـ SSE. لو النت فصل ورجع، المتصفح لوحده بيحاول يفتح الاتصال تاني من غير ما تكتب سطر كود واحد للقصة دي.
  • استهلاك أقل للموارد (Resource Efficiency): بما إن الاتصال في اتجاه واحد، فالسيرفر مش محتاج يدير طوابير معقدة للرسائل الجاية من العميل.
  • الدعم المدمج (Built-in Browser Support): مش محتاج تنزل مكتبات خارجية ضخمة، الـ EventSource API موجودة جاهزة في كل المتصفحات الحديثة.

تطبيق عملي: بناء سيرفر الإشعارات بـ Node.js و Express

تعالوا نكتب شوية كود عملي عشان الصورة توضح أكتر. هنعمل سيرفر بسيط بـ Node.js و Express عشان يبعث إشعارات كل 5 ثوانٍ للعميل.


const express = require('express');
const app = express();

app.get('/notifications-stream', (req, res) => {
    // 1. لازم نظبط الهيدرز الخاصة بالـ SSE
    res.setHeader('Content-Type', 'text/event-stream');
    res.setHeader('Cache-Control', 'no-cache');
    res.setHeader('Connection', 'keep-alive');

    // 2. إرسال رسالة ترحيبية أول ما الاتصال يفتح
    res.write('data: تم فتح قناة الإشعارات بنجاح!\n\n');

    // 3. محاكاة وصول إشعار جديد كل 5 ثواني
    const intervalId = setInterval(() => {
        const notification = JSON.stringify({ 
            title: 'إشعار جديد', 
            message: 'عندك رسالة جديدة في صندوق الوارد',
            time: new Date().toLocaleTimeString()
        });
        
        res.write(`data: ${notification}\n\n`);
    }, 5000);

    // 4. لو العميل قفل الصفحة أو الموقع، نقفل الـ Interval عشان ما نحصلش Memory Leak
    req.on('close', () => {
        clearInterval(intervalId);
        res.end();
    });
});

app.listen(3000, () => {
    console.log('Server is running on port 3000');
});

استقبال الإشعارات في المتصفح باستخدام JavaScript

دلوقتي السيرفر جاهز وبيبعث البيانات، تعالوا نشوف الناحية التانية، إزاي المتصفح هيستقبل البيانات دي ويعرضها للمستخدم بطريقة احترافية.


// التأكد من دعم المتصفح للـ EventSource
if (typeof(EventSource) !== "undefined") {
    // فتح الاتصال بمسار الـ SSE على السيرفر
    const eventSource = new EventSource('http://localhost:3000/notifications-stream');

    // الاستماع للرسائل الجاية من السيرفر
    eventSource.onmessage = function(event) {
        const data = JSON.parse(event.data);
        
        console.log("وصل إشعار جديد:", data);
        
        // هنا تقدر تعرض الإشعار للمستخدم (مثلاً باستخدام Toast Notification)
        showToast(data.title, data.message);
    };

    // التعامل مع الأخطاء لو حصلت
    eventSource.onerror = function(error) {
        console.error("حصل مشكلة في الاتصال، المتصفح هيحاول يعيد الاتصال لوحده:", error);
    };

} else {
    console.لمتصفحك لا يدعم Server-Sent Events;
}

function showToast(title, message) {
    // دالة وهمية لعرض الإشعار في الواجهة
    alert(`${title}: ${message}`);
}

إيمتى تبعد عن الـ SSE؟ (العيوب والقيود)

زي ما قلنا، مفيش تكنولوجيا مثالية في كل الظروف. الـ SSE عنده عيوب لازم تحطها في اعتبارك:

  • الاتصال في اتجاه واحد فقط: لو العميل محتاج يبعث بيانات للسيرفر في نفس القناة، الـ SSE مش هينفع لوحده وهتضطر تستخدم طلبات HTTP POST عادية.
  • حدود المتصفح لعدد الاتصالات: المتصفحات القديمة (زي بعض إصدارات إنترنت إكسبلورر القديمة أو متصفحات الموبايل المحدودة) كان عندها حد أقصى لعدد اتصالات الـ SSE المفتوحة في نفس النطاق (Domain)، رغم إن المشكلة دي اتحلت في المتصفحات الحديثة مع الـ HTTP/2.

خاتمة ونصيحة من أخ

يا بشمهندس، البرمجة مش بس إنك تستخدم أحدث وأعقد تكنولوجيا وخلاص. الهندسة الصح هي إيجاد أبسط وأنسب حل للمشكلة المطلوبة بأقل تكلفة وأعلى كفاءة. الـ Server-Sent Events (SSE) كنز مهمل كتير من المبرمجين بينسوه وبيجروا فوراً على الـ WebSockets مع إن متطلبات مشروعهم بسيطة جداً ومش محتاجة التعقيد ده كله.

جرب تفتح مشروعك الجای وتطبق فيه الـ SSE لو بتعمل نظام إشعارات أو تحديثات حية، وهتلاحظ بنفسك الفرق في سرعة التطوير وقلة المشاكل. دايمًا خلي شعارك: "البساطة هي سر الاستقرار". بالتوفيق، ومستني آرائكم وتجاربكم في الكومنتات!


Share

Related posts

Aug 10, 2026 • 2 min read
Reading Count: 8
دمج الـ GraphQL مع الـ REST في نظام واحد: متى ولماذا؟

دمج الـ GraphQL مع الـ REST في نظام واحد: متى ولماذا؟ يا هلا بيك يا باشمهندس في عالم تطوير الـ برمجي...

Aug 10, 2026 • 2 min read
Reading Count: 3
استراتيجيات بناء Webhooks آمنة وموثوقة (Retries & Signatures)

يا هلا بيك يا بشمهندس! لو بتطور نظام ويب (Web Development) وفي لحظة لقيت نفسك محتاج تربط السيرفر بتا...

Aug 10, 2026 • 2 min read
Reading Count: 9
تصميم APIs تدعم الـ Idempotency لمنع تكرار عمليات الدفع

يا هلا بيك يا بشمهندس في عالم البرمجة والـ Web Development. أحياناً بتبني نظام دفع (Payment System)...