Как создать собственную систему комментариев с помощью 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()
, чтобы избавиться от завершающей косой черты ( /
), которую Гэтсби добавляет к слагу.
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
.
Можно ли раскрывать свой ключ API Firebase?
да. Как заявил инженер 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.
Перейдите в облачный магазин FireStore. Нажмите «Начать сбор». Введите comments
для «Идентификатора коллекции», затем нажмите «Далее».
Для «ID документа» нажмите «Auto-ID. Введите следующие данные и нажмите «Сохранить».
Пока вы вводите данные, убедитесь, что «Поля» и «Типы» соответствуют скриншоту выше. Затем нажмите «Сохранить».
Вот как вы добавляете комментарий вручную в 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. Это отличный инструмент для создания безопасных и быстрых приложений.
Мы создали супер-простой раздел комментариев. Но это не мешает вам исследовать дополнительные возможности:
- Добавьте изображения профиля и сохраните их в облачном хранилище для Firebase;
- Используйте Firebase, чтобы позволить пользователям создавать учетные записи и аутентифицировать их с помощью аутентификации Firebase;
- Используйте Firebase для создания встроенных комментариев в стиле Medium.
Отличным способом начать было бы перейти к документации Firestore.
Наконец, давайте перейдем к разделу комментариев ниже и обсудим ваш опыт создания раздела комментариев с помощью Firebase.
Полезные интерфейсные и UX-функции, доставляемые раз в неделю.
С инструментами, которые помогут вам сделать вашу работу лучше. Подпишитесь и получите контрольные списки Smart Interface Design Checklists от Виталия в формате PDF по электронной почте.
На интерфейсе и UX. Нам доверяют 190 000 человек.