47

خادوم دردشة محلية كتبته بـNode.js/Express/Socket.IO/React/Redux/Webpack

  • forabi

في الفترة الماضية كنت أعمل على تطبيق يجمع ما تعلمته طيلة الشهور الفائتة (React + Redux + Webpack، ثلاث مكونات أخذت تتصاعد شعبيّتها مؤخّرًا)، فقمت بكتابة خادوم وعميل دردشة بشكل مشابه لـWhatsApp Web وبواجهة مصممة وفق Material Design، يعمل ضمن المتصفحات على الشبكة المحلية، حيث يمكن لأي جهاز على الشبكة إنشاء الخادوم ثم يمكن للأجهزة الأخرى الانضمام إليه وبدء الدردشة سويّة عبر WebSockets. يتم اكتشاف الخواديم تلقائيًّا باستخدام بروتوكول Zeroconf/Bonjour، وتستخدم Socket.IO لنقل رسائل الدردشة.

بالإضافة إلى ما سبق، استخدمت:

  • Babel طبعًا

  • Reselect لـRedux

  • Promsie middleware لـRedux

  • CSS Modules

  • ESLint

  • VSCode

فيديو يستعرض المشروع:

الخطوات القادمة:

  • تشفير الرسائل باستخدام asymmetric key encryption باستخدام واجهة التشفير WebCrypto API في المتصفحات الحديثة، يتم تطبيق التشفير بشكل شفاف (transparent) عن طريق middleware لـRedux يشفر الرسائل الصادرة ويفك تشفير الرسائل الواردة ويمررها لـلـstore.

  • تحسين المظهر (المشروع ليس إلا proof of concept)

المصدر متوفر على GitHub:

يرجى الدخول لحسابك أو تسجيل حساب لتستطيع إضافة تعليق
حساب جديد دخول

التعليقات

عمل إستثاني ورائع، نادرا ما أرى أشخاص عرب متقدمين في جافاسكربت مثلك، طالما تذهلني يا فواز

لدي بعض الاستفسارات، أين يتم تخزين الرسائل؟ كون السيرفر محلي يتم تخزين الرسائل في مكان ما؟ أفترض المتصفح؟

أيضا، ماذا عن استخدام firebase معه؟ أحاول تطوير تطبيق قريب من هذا المفهوم بنسخة متصفح وهاتف، لذا كنت أتساءل حول إمكانية نقل الأمر من المحلي إلى remote

الرسائل حاليًّا تخزن في الذاكرة فقط، لكنني بدأت العمل على تخزينها ضمن IndexedDB باستخدام redux middleware أكتبه بنفسي (حاليًّا يتم تخزين الرسائل، ولكن لا يتم عرضها عند تحديث الصفحة)، المشكلة هي أن تخزين الرسائل يعني ربط كل رسالة بالخادوم الذي تولى نقلها، ليتم عرضها فقط عند الاتصال بنفس الخادوم مجدّدًا، وهذا يعني أن كل خادوم يجب أن يحتفظ بمعرفه الخاص، ويعني عمل authentication لكل client، وعندها سينتقل الموضوع إلى استخدام قاعدة بيانات، ويزداد تعقيدًا... لكنني أعمل على ذلك، ليس فقط من أجل هذا، بل أيضًا من أجل تخزين الرسائل لإيصالها إلى الأطراف غير المتصلة عند اتصالها مجدّدًا.

يمكنك بسهولة نقله إلى خادوم غير محلي، وهذا ما كنت أفكر بفعله، قم بحذف كل ما يتعلق بـBounjour.

يمكنك تجريب استخدام DDP للتواصل

شاهدت مؤخرا تطبيق شات مشابه مبني بmeteor و DDP

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

deshasuliman أضف ردا

علاقتي بالبرمجة تشبه علاقة أمي بها بالضبط =D إلا أني شاهدت الفيديو وأعجبني صُنعك ومجهودك المبذول جليًا، أحسنت، أتمنى لك التوفيق والتقدُّم.

شكرًا جزيلًا :)

khelll أضف ردا

عمل رائع،

  • هل تخزن الرسائل بمكان ما؟

  • ماذا يحدث عند توقف السوكيت؟ وهل هناك سوكيت لكل محادثة؟

  • ماهو مفهوم الأونلاين الموجود بجانب كل محادثة؟

الرسائل حاليًا تخزن في الذاكرة، وتكرر نسخة منها وتحفظ في IndexedDB باستخدام redux middleware، لكنها لا تعرض مجدّدًا عند تحديث الصفحة، انظر ردي على @assassinateur

أونلاين يعني أن socket متصلة فقط، عند انقطاعها يبث الخادم حدثًا لكل الأطراف المتصلة بأن الطرف الفلاني قد أصبح offline، لتنعكس هذه التغييرات في الواجهة.

socket وحيدة لكل عميل تتولى الدردشة مع كل الأطراف، وsocket أخرى تتولى البحث عن الخواديم المحلية باستخدام bonjour وإيصالها للمتصفح.

أنا أعمل على مشروع مشابه لهذا لكنه موجه ل "أدمن" المواقع. يمكن للزائر مراسلة "الادمن" عبر الشات، الاضافة في مشروعي أن "الادمن" يمكنه الرد و استقبال الرسائل عبر تطبيق الواتساب.

  • أضنه يخزن الرسائل في ملفات متفرقة، لكل محادثة ملفها الخاص.

  • مفهوم الاونلاين أضنه يقصد بها حالة صاحب المحادثة : هل مازال يستقبل الرسائل أم أنه ترك رسالة وغادر.

بالتوفيق

السلام عليكم .

انت تستخدم ال phpApi الخاصة بواتساب ؟ الم تعاني من قصص حجب الرقم ؟

مع التقدير

نعم أستعمل phpApi الخاص بالواتسب لكن مشكلة حجب الرقم لم تحصل معي، على الاقل، لحد الان. لكل أدمن خصصت رقما خاصا به للتواصل لا أشارك نفس الرقم مع كل الادمنات.

اكون سعيد لو شاركتني ال WorkFlow خاصتك .

هل جربت هذه المكتبة في التخزين المؤقت للرسائل

محتويات الصفحة تبقى حتى بعد اعادة التحميل .

هذه تعتمد على localStorage API وهي واجهة blocking أي أنها تعيق أي عمل في صفحة الويب (حتى النقر على الأزرار)، ليست مناسبة، كون الرسائل ستصل بفواصل لحظات. ليست المشكلة بالتخزين ذاته، وإنما بما يتعلق به من تعقيدات، راجع ردودي أعلاه.

أنا على وشك بدأ مشواري في جافاسكريبت و أطمح للإحتراف فيها إن شاء الله , هل من نصائح ؟

ابدأ أوّلا بتعلم JavaScript على Codecademy.

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

صُدمت للوهلة الأولى عندما رأيت زر ابدأ الخاص بويندوز D:

حاولت فهم الفائدة من Redux لكن لم أصل لنتيجة بعد، ربما ﻷني ما زلت أعمل بمشاريع تتعلق بـ Angular وعقلي ما زال يركز فيها.

لو تضع لنا بعض المقالات التعريفية لـ Redux ومكاتبها التي استخدمتها تكون وفّرت علينا عناء البحث عنها P:

React ليست إطار عمل، وهي فكرة يكررها كثيرًا أنصارها والعاملون على تطويرها، React مسؤولة فقط عن عرض العناصر في الصفحة. ما زلت تحتاج إلى طريقة لإدارة المعلومات في الصفحة، هناك أساليب مختلفة ذلك، لكن مطوّري React ينصحون باعتماد بنية Flux، أو انسياب البيانات باتجاه واحد. معنى ذلك أن المُكوّنات غير مرتبطة ببعضها، ولا تقوم بتعديل البيانات مباشرة، بل تستقي البيانات من مصدر أعلى منها، وإذا أرادت تعديل البيانات فهي تُرسل "حدثًا action" يصف التغيير المطلوب إلى "مستودع store" من مستودعات البيانات. يقوم المستودع بتعديل البيانات بالشكل المطلوب، ثمّ تُعيد React رسم كل المُكوّنات المُعتمدة على الجزء المتغيّر من البيانات. فائدة ذلك هو أنّ المُكوّنات لا تحتاج إلى أن تعلم إن كانت مكوّنات أخرى في الصّفحة تعتمد على البيانات الّتي تعدّلها، بل فقط تهتمّ بنفسها وتعبّر عن رغبتها بتعديل البيانات في المصدر الأعلى، وهذا يؤدّي إلى تدفّق "flow" البيانات من أعلى إلى أسفل فقط، وليس باتّجاهين (two-way data binding) أي بين المكوّنات نفسها كما في Angular.

Redux تذهب أبعد من ذلك، وقد أصبحت المعيار الذّهبي لبنية Flux، لأنّها تقوم بإنشاء مستودع وحيد يحتوي كلّ بيانات التطبيق، وتقوم المكوّنات بإرسال حدث التّغيير إلى هذا المستودع الّذي يقوم عندها استدعاء وظيفة تستقبل النسخة السابقة من المستودع، وتُعيد نسخة جديدة، وهكذا في كلّ تغيير. معنى ذلك أنّ وظيفة التّغيير (التي تُسمى reducer) هي وظيفة صافية (pure function) لا تعلم شيئًا عن برنامجك، بل فقط تأخذ الحالة السابقة والحدث الحالي، وتُعيد حالة جديدة.

بساطة هذه البنية هي نقطة القوة في Redux، وهي التي تسمح لتطبيقك بأن يكون قابلًا للاختبار بسهولة (unit tests)، كون المكوّنات تستقي البيانات من مصدر أعلى، وتعبّر فقط عن رغبتها بتعديلها، ولا تقوم بتعديلها مباشرة، وهذا يجعل كل مكوّن قابلًا للاختبار بصورة منفصلة، كما أنّه يسهل اختبار وظيفة reducer، لأنّها لا تعلم شيئًا عن التطبيق، بل تحتاج فقط الحدث والحالة الحالية، لتعطيك حالة جديدة.

هناك دورتان لـDan Abramov كاتب Redux، متوفّرتان مجانًا على Egghead.io، أنصح بهما بشدّة:

رد كافي ووافي، جزاك الله خيراً :)

هل أحتاج لتعلم React بشكل جيد قبل حضور دورتي Redux؟

Redux ليست مرتبطة بـReact حصرًا، يمكنك استعمالها في أطر عمل أخرى. ويمكنك تعلّمها بمفردها.