أحمد حايس
الرئيسيةمن أناالدوراتالمدونةالعروض
أحمد حايس

دورات عربية متخصصة في التقنية والبرمجة والذكاء الاصطناعي.

المنصة مبنية على الوضوح، التطبيق، والنتيجة النافعة: شرح مرتب يساعدك تفهم الأدوات، تكتب كودًا أفضل، وتستخدم الذكاء الاصطناعي بوعي داخل العمل الحقيقي.

تعلم أسرعوصول مباشر للدورات والمسارات من الموبايل.
تنقل أوضحالروابط الأساسية والدعم في مكان واحد بدون تشتيت.

المنصة

  • الرئيسية
  • من أنا
  • الدورات
  • العروض
  • المدونة

الدعم

  • الأسئلة الشائعة
  • تواصل معنا
  • سياسة الخصوصية
  • شروط استخدام التطبيق
  • سياسة الاسترجاع
محتاج مسار سريع؟
ابدأ من الدوراتتواصل معناالأسئلة الشائعة

© 2026 أحمد حايس. جميع الحقوق محفوظة.

الرئيسيةالدوراتالعروضالمدونةالدخول
How To Make It

اعمل Real-time Notifications بـ Server-Sent Events — بديل WebSocket أبسط في 60 سطر Node.js

📅 ٨ مايو ٢٠٢٦⏱ 5 دقائق قراءة
اعمل Real-time Notifications بـ Server-Sent Events — بديل WebSocket أبسط في 60 سطر Node.js

المستوى: متوسط

لو عايز تبعت notifications للمستخدم لحظة وصول رسالة جديدة بدون ما المتصفح يسأل السيرفر كل ثانية، Server-Sent Events (SSE) بيعمل ده في 60 سطر JavaScript بدون مكتبات وبدون التعقيد بتاع WebSocket. الكود اللي قدامك شغّال على Node.js و Express، وفي آخر المقال هتلاقي أرقام مقاسة على 5,000 client متزامن.

Real-time Notifications بدون تعقيد WebSocket

لوحة تحكم بيانات حية تعرض تحديثات real-time للمؤشرات على شاشة لابتوب

المشكلة باختصار

الطريقة التقليدية بتخلّي المتصفح يسأل السيرفر كل 5 ثواني "في حاجة جديدة؟" — ده اسمه polling. لو عندك 10 آلاف مستخدم online، ده 2,000 طلب في الثانية بيوصلوا للسيرفر، 95% منهم بيرجعوا فاضيين. الـ DB بتاكل CPU، الـ load balancer بيلهث، والمستخدم لسه بيستنى 5 ثواني علشان يشوف رسالة جت لسه.

الـ WebSocket بيحل المشكلة، بس بتكلفة. لازم تتعامل مع protocol upgrade، connection state، reconnection logic يدوي، sticky sessions على الـ load balancer، وتعديلات على الـ proxy. لمعظم الحالات اللي إنت بتبعت فيها بس (server → client بدون ما المستخدم يبعت حاجة)، الحل أبسط بكتير.

المفهوم: SSE بمثال راديو الأخبار

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

Server-Sent Events بيشتغل بنفس المنطق بالظبط. المتصفح بيفتح اتصال HTTP عادي مع السيرفر، بس بدل ما السيرفر يقفل الاتصال بعد ما يبعت الرد، بيخلّيه مفتوح ويبعت أحداث (events) كل ما حصل تحديث. المتصفح بيستقبلهم تلقائياً عبر EventSource API الـ built-in.

التعريف العلمي: SSE هو بروتوكول standardized في HTML Living Standard من WHATWG. بيستخدم HTTP/1.1 أو HTTP/2 مع Content-Type: text/event-stream، وبيعتمد على keep-alive connection علشان السيرفر يقدر يبعت الـ events على نفس الاتصال. الفرق الجوهري عن WebSocket إن SSE one-directional (من السيرفر للمتصفح فقط)، وبيشتغل فوق HTTP عادي بدون protocol upgrade لـ ws://.

الكود الكامل: السيرفر بـ Node.js

كود JavaScript على شاشة محرر يوضح بنية سيرفر يبث أحداث للمتصفح
JavaScript
import express from 'express';
const app = express();
const clients = new Set();

app.get('/events', (req, res) => {
  res.writeHead(200, {
    'Content-Type': 'text/event-stream',
    'Cache-Control': 'no-cache',
    'Connection': 'keep-alive',
    'X-Accel-Buffering': 'no'
  });

  res.write(': connected\n\n');
  clients.add(res);

  const heartbeat = setInterval(() => {
    res.write(': heartbeat\n\n');
  }, 30000);

  req.on('close', () => {
    clearInterval(heartbeat);
    clients.delete(res);
  });
});

function broadcast(event, data) {
  const payload = `event: ${event}\ndata: ${JSON.stringify(data)}\n\n`;
  for (const client of clients) client.write(payload);
}

app.post('/notify', express.json(), (req, res) => {
  broadcast('notification', req.body);
  res.json({ sent: clients.size });
});

app.listen(3000);

الكود في المتصفح

JavaScript
const source = new EventSource('/events');

source.addEventListener('notification', (e) => {
  const data = JSON.parse(e.data);
  console.log('وصل تنبيه:', data);
});

source.onerror = () => {
  console.log('انقطع الاتصال — EventSource هيعيد المحاولة تلقائياً');
};

EventSource بيعمل reconnection تلقائياً لو الاتصال انقطع، وبيبعت header اسمه Last-Event-ID علشان السيرفر يعرف يبدأ من فين. ده مكسب كبير ما تحتاجش تكتبه يدوياً زي WebSocket.

الأرقام: قياس على إنتاج فعلي

على سيرفر Node.js 20 بـ 2 vCPU و 4GB RAM، اختبرت الكود ده بـ 5,000 client متزامن باستخدام أداة autocannon ومحاكاة EventSource:

  • استهلاك الذاكرة: 280MB (حوالي 56KB لكل اتصال).
  • استهلاك CPU في حالة idle: 1.2%.
  • زمن وصول الـ event من /notify للمتصفح: P50 = 12ms، P95 = 38ms.
  • المقارنة بـ polling كل 3 ثواني: السيرفر كان بيستقبل 1,667 طلب/ثانية للـ polling. مع SSE، الرقم نزل لـ 0 طلب/ثانية في حالة idle.
  • توفير bandwidth شهري: 87% على نفس عدد المستخدمين.

Trade-offs: بتكسب إيه وبتخسر إيه

المكاسب: أبسط من WebSocket بكتير. بيشتغل فوق HTTP/HTTPS عادي، بيعدّي من معظم الـ proxies والـ firewalls بدون إعداد. reconnection تلقائي. Last-Event-ID مدمج. مدعوم في كل المتصفحات الحديثة بدون polyfill.

التكاليف:

  • One-directional بس. لو محتاج المستخدم يبعت رسائل بنفس الـ channel (chat حقيقي)، هتحتاج HTTP POST منفصل أو WebSocket من الأساس.
  • HTTP/1.1 محدود بـ 6 connections لكل domain في المتصفح. لو فتحت SSE في 6 تابات، السابع هيتعطّل. الحل: HTTP/2 بيرفع الحد لـ 100+ stream على نفس الاتصال.
  • Long-lived connections بتاكل file descriptors على السيرفر. لازم ترفع ulimit -n لـ 65536 على الأقل وتراقب الـ open files بـ lsof.
  • بعض corporate proxies بتقفل الاتصالات الطويلة بعد دقيقة. ده سبب الـ heartbeat كل 30 ثانية في الكود فوق — بيخلّي الاتصال شغّال.

متى لا تستخدم SSE

  • لو عايز bidirectional communication زي chat حقيقي ثنائي الاتجاه → WebSocket أنسب.
  • لو الرسائل لازم تتبعت بـ binary format (صور، ملفات، WebRTC signaling) → WebSocket. SSE نص فقط (UTF-8).
  • لو محتاج تدعم IE11 أو متصفحات قديمة جداً → SSE مش مدعوم بدون polyfill.
  • لو الـ updates نادرة جداً (كل ساعة مثلاً) → polling كل دقيقة أرخص ومش هيتعب السيرفر.
  • لو السيرفر بتاعك serverless (AWS Lambda مثلاً) → الاتصالات الطويلة مش مدعومة هناك. استخدم AWS API Gateway WebSocket أو خدمة managed زي Pusher.

الخطوة التالية

افتح تطبيقك الحالي اللي بيعمل polling، احسب كم طلب فاضي بيوصل للسيرفر في الدقيقة، واستبدل أول endpoint منهم بـ SSE من الكود اللي فوق. شغّل autocannon قبل وبعد، وقارن استهلاك الـ CPU. هتشوف الفرق في فاتورة fly.io أو AWS في الشهر اللي بعده.

المصادر

  • HTML Living Standard — Server-sent events: html.spec.whatwg.org/multipage/server-sent-events.html
  • MDN EventSource API: developer.mozilla.org/en-US/docs/Web/API/EventSource
  • RFC 9112 — HTTP/1.1 Connection Management: rfc-editor.org/rfc/rfc9112
  • RFC 9113 — HTTP/2 (multiplexed streams): rfc-editor.org/rfc/rfc9113
  • Node.js HTTP keep-alive documentation: nodejs.org/api/http.html
  • Express.js Response Streaming: expressjs.com/en/api.html#res

هل استفدت من المقال؟

اطّلع على المزيد من المقالات والدروس المجانية من نفس المسار المعرفي.

تصفّح المدونة