كيفية إنشاء نظام التعليقات الخاص بك باستخدام Firebase
نشرت: 2022-03-10يعد قسم التعليقات طريقة رائعة لبناء مجتمع لمدونتك. عندما بدأت التدوين مؤخرًا ، فكرت في إضافة قسم التعليقات. ومع ذلك ، لم يكن الأمر سهلاً. تأتي أنظمة التعليقات المستضافة ، مثل Disqus و Commento ، مع مجموعة المشاكل الخاصة بها:
- هم يمتلكون بياناتك.
- هم ليسوا أحرار.
- لا يمكنك تخصيصهم كثيرا.
لذلك ، قررت بناء نظام التعليقات الخاص بي. بدا Firebase كبديل استضافة مثالي لتشغيل خادم خلفي.
بادئ ذي بدء ، ستحصل على جميع مزايا امتلاك قاعدة بيانات خاصة بك: أنت تتحكم في البيانات ، ويمكنك هيكلتها بالشكل الذي تريده. ثانيًا ، لا تحتاج إلى إعداد خادم خلفية. يمكنك التحكم فيه بسهولة من الواجهة الأمامية. إنه مثل امتلاك أفضل ما في العالمين: نظام مستضاف بدون متاعب الواجهة الخلفية.
في هذا المنشور ، هذا ما سنفعله. سنتعلم كيفية إعداد Firebase باستخدام Gatsby ، وهو منشئ موقع ثابت. ولكن يمكن تطبيق المبادئ على أي مولد موقع ثابت.
دعونا نتعمق!
ما هو Firebase؟
Firebase هو نهاية خلفية كخدمة تقدم أدوات لمطوري التطبيقات مثل قاعدة البيانات والاستضافة والوظائف السحابية والمصادقة والتحليلات والتخزين.
Cloud Firestore (قاعدة بيانات Firebase) هي الوظيفة التي سنستخدمها لهذا المشروع. إنها قاعدة بيانات NoSQL. هذا يعني أنه ليس منظمًا مثل قاعدة بيانات SQL مع الصفوف والأعمدة والجداول. يمكنك التفكير في الأمر على أنه شجرة JSON كبيرة.
مقدمة عن المشروع
دعنا نبدأ المشروع عن طريق استنساخ أو تنزيل المستودع من GitHub.
لقد قمت بإنشاء فرعين لكل خطوة (واحد في البداية والآخر في النهاية) لتسهيل تتبع التغييرات أثناء تقدمنا.
لنقم بتشغيل المشروع باستخدام الأمر التالي:
gatsby develop
إذا فتحت المشروع في متصفحك ، فسترى العناصر الأساسية لمدونة أساسية.
قسم التعليقات لا يعمل. إنه مجرد تحميل نموذج للتعليق ، وعند إرسال التعليق ، فإنه يسجل التفاصيل في وحدة التحكم.
مهمتنا الرئيسية هي جعل قسم التعليقات يعمل.
كيف يعمل قسم التعليقات
قبل القيام بأي شيء ، دعنا نفهم كيفية عمل كود قسم التعليقات.
أربعة مكونات تتعامل مع أقسام التعليقات:
-
blog-post.js
-
Comments.js
-
CommentForm.js
-
Comment.js
أولاً ، نحتاج إلى تحديد التعليقات على المنشور. يمكن القيام بذلك عن طريق إنشاء معرّف فريد لكل منشور مدونة ، أو يمكننا استخدام الرابط الثابت ، وهو فريد دائمًا.
ملف blog-post.js
هو مكون التخطيط لجميع منشورات المدونة. إنها نقطة الدخول المثالية للحصول على سبيكة من منشور مدونة. يتم ذلك باستخدام استعلام GraphQL.
export const query = graphql` query($slug: String!) { markdownRemark(fields: { slug: { eq: $slug } }) { html frontmatter { title } fields { slug } } } `
قبل إرسالها إلى مكون Comments.js
، دعنا نستخدم طريقة substring()
للتخلص من الشرطة المائلة اللاحقة ( /
) التي يضيفها Gatsby إلى slug.
const slug = post.fields.slug.substring(1, post.fields.slug.length - 1) return ( <Layout> <div className="container"> <h1>{post.frontmatter.title}</h1> <div dangerouslySetInnerHTML={{ __html: post.html }} /> <Comments comments={comments} slug={slug} /> </div> </Layout> ) }
يقوم المكون Comments.js
بتعيين كل تعليق ويمرر بياناته إلى Comment.js
، إلى جانب أي ردود. بالنسبة لهذا المشروع ، قررت أن أتعمق بمستوى واحد في نظام التعليقات.
يقوم المكون أيضًا بتحميل CommentForm.js
لالتقاط أي تعليقات ذات مستوى أعلى.
const Comments = ({ comments, slug }) => { return ( <div> <h2>Join the discussion</h2> <CommentForm slug={slug} /> <CommentList> {comments.length > 0 && comments .filter(comment => !comment.pId) .map(comment => { let child if (comment.id) { child = comments.find(c => comment.id === c.pId) } return ( <Comment key={comment.id} child={child} comment={comment} slug={slug} /> ) })} </CommentList> </div> ) }
دعنا ننتقل إلى CommentForm.js
. هذا الملف بسيط ، ويقدم نموذج تعليق ويتعامل مع إرساله. طريقة التقديم ببساطة تسجل التفاصيل إلى وحدة التحكم.
const handleCommentSubmission = async e => { e. preventDefault() let comment = { name: name, content: content, pId: parentId ∣∣ null, time: new Date(), } setName("") setContent("") console.log(comment) }
هناك الكثير مما يحدث في ملف Comment.js
. دعونا نقسمها إلى أجزاء أصغر.
أولاً ، هناك مكون SingleComment
، والذي يعرض تعليقًا.
أنا أستخدم Adorable API للحصول على صورة رمزية رائعة. تُستخدم مكتبة Moment.js لعرض الوقت بتنسيق يمكن للبشر قراءته.
const SingleComment = ({ comment }) => ( <div> <div className="flex-container"> <div className="flex"> <img src="https://api.adorable.io/avazars/65/[email protected]" alt="Avatar" /> </div> <div className="flex"> <p className="comment-author"> {comment.name} <span>says</span> </p> {comment.time} &&(<time>(moment(comment.time.toDate()).calendar()}</time>)} </div> </div> </p>{comment.content}</p> </div> )
التالي في الملف هو مكون Comment
. يعرض هذا المكون تعليقًا فرعيًا إذا تم تمرير أي تعليق فرعي إليه. بخلاف ذلك ، فإنه يعرض مربع رد ، والذي يمكن تشغيله وإيقاف تشغيله بالنقر فوق الزر "رد" أو الزر "إلغاء الرد".
const Comment = ({ comment, child, slug }) => { const [showReplyBox, setShowReplyBox] = useState(false) return ( <CommentBox> <SingleComment comment={comment} /> {child && ( <CommentBox child className=comment-reply"> <SingleComment comment={child} /> </CommentBox> )} {!child && ( <div> {showReplyBox ? ( <div> <button className="btn bare" onClick={() => setShowReplyBoy(false)} > Cancel Reply </button> <CommentForm parentId={comment.id} slug={slug} /> </div> ) : ( <button className="btn bare" onClick={() => setShowReplyBox(true)}> Reply </button> )} </div> )} </div> )} </CommentBox>
الآن بعد أن أصبح لدينا نظرة عامة ، دعنا ننتقل إلى خطوات قسم التعليقات الخاصة بنا.
1. أضف Firebase
أولاً ، لنقم بإعداد Firebase لمشروعنا.
ابدأ بالتسجيل. انتقل إلى Firebase ، واشترك في حساب Google. إذا لم يكن لديك واحد ، فانقر فوق "البدء".
انقر فوق "إضافة مشروع" لإضافة مشروع جديد. أضف اسمًا لمشروعك ، وانقر على "إنشاء مشروع".
بمجرد إنشاء مشروع ، سنحتاج إلى إعداد Cloud Firestore.
في القائمة اليسرى ، انقر على "قاعدة بيانات". بمجرد فتح صفحة تقول "Cloud Firestore" ، انقر على "إنشاء قاعدة بيانات" لإنشاء قاعدة بيانات Cloud Firestore جديدة.
عندما تظهر النافذة المنبثقة ، اختر "ابدأ في وضع الاختبار". بعد ذلك ، اختر موقع Cloud Firestore الأقرب إليك.
بمجرد رؤية صفحة مثل هذه ، فهذا يعني أنك قمت بإنشاء قاعدة بيانات Cloud Firestore الخاصة بك بنجاح.
لننتهي من إعداد منطق التطبيق. ارجع إلى التطبيق وثبّت Firebase:
yarn add firebase
أضف ملفًا جديدًا ، firebase.js
، في الدليل الجذر. الصق هذا المحتوى فيه:
import firebase from "firebase/app" import "firebase/firestore" var firebaseConfig = 'yourFirebaseConfig' firebase.initializeApp(firebaseConfig) export const firestore = firebase.firestore() export default firebase
ستحتاج إلى استبدال yourFirebaseConfig
. للعثور عليه ، انقر على رمز الترس بجوار "نظرة عامة على المشروع" في تطبيق Firebase.
هذا يفتح صفحة الإعدادات. تحت العنوان الفرعي لتطبيقك ، انقر فوق رمز الويب ، الذي يبدو كالتالي:
هذا يفتح نافذة منبثقة. في حقل "لقب التطبيق" ، أدخل أي اسم وانقر على "تسجيل التطبيق". سيعطي هذا كائن firebaseConfig
الخاص بك.
<!-- The core Firebase JS SDK is always required and must be listed first --> <script src="https://www.gstatic.com/firebasejs/7.15.5/firebase-app.js"></script> <!-- TODO: Add SDKs for Firebase products that you want to use https://firebase.google.com/docs/web/setup#available-libraries --> <script> // Your web app's Firebase configuration var firebaseConfig = { ... }; // Initialize Firebase firbase.initializeApp(firebaseConfig); </script>
انسخ محتويات كائن firebaseConfig
فقط ، والصقها في ملف firebase.js
.
هل من المقبول الكشف عن مفتاح Firebase API الخاص بك؟
نعم. كما ذكر أحد مهندسي Google ، فإن تعريض مفتاح API الخاص بك على ما يرام.
الغرض الوحيد من مفتاح API هو تحديد مشروعك بقاعدة البيانات في Google. إذا قمت بتعيين قواعد أمان قوية لـ Cloud Firestore ، فلا داعي للقلق إذا حصل شخص ما على مفتاح API الخاص بك.
سنتحدث عن قواعد الأمان في القسم الأخير.
في الوقت الحالي ، نقوم بتشغيل Firestore في وضع الاختبار ، لذا يجب ألا تكشف عن مفتاح API للجمهور.
كيفية استخدام Firestore؟
يمكنك تخزين البيانات في أحد نوعين:
- مجموعة
مجموعة تحتوي على وثائق. إنها مثل مجموعة من الوثائق. - وثيقة
يحتوي المستند على بيانات في زوج من قيم الحقل.
تذكر أن المجموعة قد تحتوي على مستندات فقط وليس مجموعات أخرى. لكن المستند قد يحتوي على مجموعات أخرى.
هذا يعني أنه إذا أردنا تخزين مجموعة داخل مجموعة ، فسنخزن المجموعة في مستند ونخزن ذلك المستند في مجموعة ، مثل:
{collection-1}/{document}/{collection-2}
كيف يتم تنظيم البيانات؟
يعد Cloud Firestore ذا طبيعة هرمية ، لذا يميل الأشخاص إلى تخزين بيانات مثل هذه:
blog/{blog-post-1}/content/comments/{comment-1}
لكن تخزين البيانات بهذه الطريقة غالبًا ما يؤدي إلى مشاكل.
قل أنك تريد الحصول على تعليق. سيتعين عليك البحث عن التعليق المخزن بعمق داخل مجموعة المدونة. هذا سيجعل التعليمات البرمجية الخاصة بك أكثر عرضة للخطأ. يوصي كريس إسبلين بعدم استخدام المجموعات الفرعية مطلقًا.
أوصي بتخزين البيانات ككائن مسطح:
blog-posts/{blog-post-1} comments/{comment-1}
بهذه الطريقة ، يمكنك الحصول على البيانات وإرسالها بسهولة.
كيف تحصل على البيانات من Firestore؟
للحصول على البيانات ، يمنحك Firebase طريقتين:
-
get()
هذا للحصول على المحتوى مرة واحدة. -
onSnapshot()
ترسل لك هذه الطريقة بيانات ثم تستمر في إرسال التحديثات ما لم تقم بإلغاء الاشتراك.
كيف ترسل البيانات إلى Firestore؟
تمامًا مثل الحصول على البيانات ، لدى Firebase طريقتان لحفظ البيانات:
-
set()
يستخدم هذا لتحديد معرف المستند. -
add()
يستخدم هذا لإنشاء مستندات بمعرفات تلقائية.
أعلم أن هذا كان كثيرًا لفهمه. لكن لا تقلق ، سوف نعيد النظر في هذه المفاهيم مرة أخرى عندما نصل إلى المشروع.
2. إنشاء تاريخ العينة
الخطوة التالية هي إنشاء بعض البيانات النموذجية لنا للاستعلام عنها. لنفعل ذلك بالذهاب إلى Firebase.
انتقل إلى Cloud Firestore. انقر فوق "بدء مجموعة". أدخل comments
لـ "معرف المجموعة" ، ثم انقر فوق "التالي".
بالنسبة إلى "معرف المستند" ، انقر فوق "معرف تلقائي". أدخل البيانات التالية وانقر على "حفظ".
أثناء إدخال البيانات ، تأكد من تطابق "الحقول" و "الأنواع" مع لقطة الشاشة أعلاه. ثم انقر فوق "حفظ".
هذه هي الطريقة التي تضيف بها تعليقًا يدويًا في Firestore. تبدو العملية مرهقة ، لكن لا تقلق: من الآن فصاعدًا ، سيهتم تطبيقنا بإضافة التعليقات.
في هذه المرحلة ، تبدو قاعدة بياناتنا على النحو التالي: comments/{comment}
.
3. احصل على بيانات التعليقات
البيانات النموذجية لدينا جاهزة للاستعلام. لنبدأ بالحصول على البيانات الخاصة بمدونتنا.
انتقل إلى blog-post.js
، واستورد Firestore من ملف Firebase الذي أنشأناه للتو.
import {firestore} from "../../firebase.js"
للاستعلام ، سنستخدم الخطاف useEffect
من React. إذا لم تكن قد قمت بذلك بالفعل ، فلنستورده أيضًا.
useEffect(() => { firestore .collection(`comments`) .onSnapshot(snapshot => { const posts = snapshot.docs .filter(doc => doc.data().slug === slug) .map(doc => { return { id: doc.id, ...doc.data() } }) setComments(posts) }) }, [slug])
الطريقة المستخدمة للحصول على البيانات هي onSnapshot
. هذا لأننا نريد أيضًا الاستماع إلى تغييرات الحالة. لذلك ، سيتم تحديث التعليقات دون أن يضطر المستخدم إلى تحديث المتصفح.
استخدمنا أساليب filter
map
للعثور على التعليقات التي تطابق سبيكةها الثابتة الحالية.
آخر شيء نحتاج إلى التفكير فيه هو التنظيف. نظرًا لاستمرار onSnapshot
في إرسال التحديثات ، فقد يؤدي ذلك إلى حدوث تسرب للذاكرة في تطبيقنا. لحسن الحظ ، يوفر Firebase إصلاحًا رائعًا.
useEffect(() => { const cleanUp = firestore .doc(`comments/${slug}`) .collection("comments") .onSnapshot(snapshot => { const posts = snapshot.docs.map(doc => { return { id: doc.id, ...doc.data() } }) setComments(posts) }) return () => cleanUp() }, [slug])
بمجرد الانتهاء من ذلك ، قم بتشغيل gatsby develop
لرؤية التغييرات. يمكننا الآن رؤية قسم التعليقات لدينا وهو يحصل على البيانات من Firebase.
لنعمل على تخزين التعليقات.
4. تعليقات المتجر
لتخزين التعليقات ، انتقل إلى ملف CommentForm.js
. دعنا نستورد Firestore في هذا الملف أيضًا.
import { firestore } from "../../firebase.js"
لحفظ تعليق في Firebase ، سنستخدم طريقة add()
، لأننا نريد من Firestore إنشاء مستندات بمعرف تلقائي.
لنفعل ذلك في طريقة handleCommentSubmission
.
firestore .collection(`comments`) .add(comment) .catch(err => { console.error('error adding comment: ', err) })
أولاً ، نحصل على المرجع لمجموعة التعليقات ، ثم نضيف التعليق. نحن نستخدم أيضًا طريقة catch
للقبض على أي أخطاء أثناء إضافة التعليقات.
في هذه المرحلة ، إذا فتحت متصفحًا ، يمكنك رؤية قسم التعليقات يعمل. يمكننا إضافة تعليقات جديدة ، وكذلك نشر الردود. المدهش أكثر هو أن كل شيء يعمل دون الحاجة إلى تحديث الصفحة.
يمكنك أيضًا التحقق من Firestore لمعرفة أنه يقوم بتخزين البيانات.
أخيرًا ، لنتحدث عن شيء مهم واحد في Firebase: قواعد الأمان.
5. تشديد قواعد الأمن
حتى الآن ، كنا نشغل Cloud Firestore في وضع الاختبار. هذا يعني أن أي شخص لديه حق الوصول إلى عنوان URL يمكنه إضافة وقراءة قاعدة البيانات الخاصة بنا. هذا مخيف.
لمعالجة ذلك ، يزودنا Firebase بقواعد الأمان. يمكننا إنشاء نمط قاعدة بيانات وتقييد أنشطة معينة في Cloud Firestore.
بالإضافة إلى العمليتين الأساسيتين (القراءة والكتابة) ، يوفر Firebase المزيد من العمليات الدقيقة: الحصول على ، وإدراج ، وإنشاء ، وتحديث ، وحذف.
يمكن تقسيم عملية القراءة على النحو التالي:
-
get
احصل على مستند واحد. -
list
الحصول على قائمة الوثائق أو مجموعة.
يمكن تقسيم عملية الكتابة على النحو التالي:
-
create
قم بإنشاء مستند جديد. -
update
قم بتحديث مستند موجود. -
delete
احذف مستند.
لتأمين التطبيق ، عد إلى Cloud Firestore. ضمن "القواعد" ، أدخل هذا:
service cloud.firestore { match /databases/{database}/documents { match /comments/{id=**} { allow read, create; } } }
في السطر الأول ، نحدد الخدمة ، والتي ، في حالتنا ، هي Firestore. تخبر الأسطر التالية Firebase أنه يمكن قراءة وإنشاء أي شيء داخل مجموعة comments
.
إذا استخدمنا هذا:
allow read, write;
... هذا يعني أنه يمكن للمستخدمين تحديث وحذف التعليقات الموجودة ، وهو ما لا نريده.
تعتبر قواعد أمان Firebase قوية للغاية ، حيث تسمح لنا بتقييد بعض البيانات والأنشطة وحتى المستخدمين.
في بناء قسم التعليقات الخاصة بك
تهاني! لقد رأيت للتو قوة Firebase. إنها أداة ممتازة لإنشاء تطبيقات آمنة وسريعة.
لقد قمنا ببناء قسم التعليقات في غاية البساطة. ولكن ليس هناك ما يمنعك من استكشاف المزيد من الاحتمالات:
- إضافة صور الملف الشخصي وتخزينها في Cloud Storage for Firebase ؛
- استخدم Firebase للسماح للمستخدمين بإنشاء حساب والمصادقة عليهم باستخدام مصادقة Firebase ؛
- استخدم Firebase لإنشاء تعليقات مضمنة شبيهة بالمتوسط.
طريقة رائعة للبدء هي التوجه إلى وثائق Firestore.
أخيرًا ، دعنا ننتقل إلى قسم التعليقات أدناه ونناقش تجربتك مع إنشاء قسم التعليقات باستخدام Firebase.
واجهة أمامية مفيدة وبتات UX مفيدة ، يتم تسليمها مرة واحدة في الأسبوع.
مع الأدوات التي تساعدك على إنجاز عملك بشكل أفضل. اشترك واحصل على قوائم التحقق من تصميم الواجهة الذكية من Vitaly بتنسيق PDF عبر البريد الإلكتروني.
على الواجهة الأمامية وتجربة المستخدم. يثق به 190.000 شخص.