Como construir seu próprio sistema de comentários usando o Firebase

Publicados: 2022-03-10
Resumo rápido ↬ Sempre quis ter uma seção de comentários para o seu blog, mas ficou sobrecarregado com as soluções de alto custo e manutenção? O Firebase pode ser seu salvador. Neste guia, aprenderemos como adicionar uma seção de comentários ao seu blog com o Firebase, enquanto aprendemos os conceitos básicos do Firebase.

Uma seção de comentários é uma ótima maneira de construir uma comunidade para o seu blog. Recentemente, quando comecei a blogar, pensei em adicionar uma seção de comentários. No entanto, não foi fácil. Sistemas de comentários hospedados, como Disqus e Commento, vêm com seu próprio conjunto de problemas:

  • Eles possuem seus dados.
  • Eles não são gratuitos.
  • Você não pode personalizá-los muito.

Então, decidi construir meu próprio sistema de comentários. O Firebase parecia uma alternativa de hospedagem perfeita para executar um servidor back-end.

Em primeiro lugar, você obtém todos os benefícios de ter seu próprio banco de dados: você controla os dados e pode estruturá-los como quiser. Em segundo lugar, você não precisa configurar um servidor back-end. Você pode controlá-lo facilmente a partir do front-end. É como ter o melhor dos dois mundos: um sistema hospedado sem o incômodo de um back-end.

Neste post, é isso que faremos. Aprenderemos como configurar o Firebase com o Gatsby, um gerador de sites estáticos. Mas os princípios podem ser aplicados a qualquer gerador de site estático.

Vamos mergulhar!

O que é Firebase?

O Firebase é um back-end como serviço que oferece ferramentas para desenvolvedores de aplicativos, como banco de dados, hospedagem, funções de nuvem, autenticação, análise e armazenamento.

Cloud Firestore (banco de dados do Firebase) é a funcionalidade que usaremos para este projeto. É um banco de dados NoSQL. Isso significa que não é estruturado como um banco de dados SQL com linhas, colunas e tabelas. Você pode pensar nisso como uma grande árvore JSON.

Introdução ao Projeto

Vamos inicializar o projeto clonando ou baixando o repositório do GitHub.

Criei duas ramificações para cada etapa (uma no início e outra no final) para facilitar o acompanhamento das alterações à medida que avançamos.

Vamos executar o projeto usando o seguinte comando:

 gatsby develop

Se você abrir o projeto em seu navegador, verá o esqueleto de um blog básico.

Blogue básico
(Visualização grande)

A seção de comentários não está funcionando. Ele está simplesmente carregando um comentário de amostra e, após o envio do comentário, registra os detalhes no console.

Nossa principal tarefa é fazer com que a seção de comentários funcione.

Mais depois do salto! Continue lendo abaixo ↓

Como funciona a seção de comentários

Antes de fazer qualquer coisa, vamos entender como funciona o código da seção de comentários.

Quatro componentes estão lidando com as seções de comentários:

  • blog-post.js
  • Comments.js
  • CommentForm.js
  • Comment.js

Primeiro, precisamos identificar os comentários de uma postagem. Isso pode ser feito criando um ID exclusivo para cada postagem do blog, ou podemos usar o slug, que é sempre único.

O arquivo blog-post.js é o componente de layout para todas as postagens do blog. É o ponto de entrada perfeito para obter a lesma de uma postagem no blog. Isso é feito usando uma consulta GraphQL.

 export const query = graphql` query($slug: String!) { markdownRemark(fields: { slug: { eq: $slug } }) { html frontmatter { title } fields { slug } } } `

Antes de enviá-lo para o componente Comments.js , vamos usar o método substring() para eliminar a barra final ( / ) que Gatsby adiciona ao 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> ) }

O componente Comments.js mapeia cada comentário e passa seus dados para Comment.js , junto com todas as respostas. Para este projeto, decidi aprofundar o sistema de comentários.

O componente também carrega CommentForm.js para capturar quaisquer comentários de nível superior.

 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> ) }

Vamos passar para CommentForm.js . Este arquivo é simples, renderizando um formulário de comentários e processando seu envio. O método de envio simplesmente registra os detalhes no console.

 const handleCommentSubmission = async e => { e. preventDefault() let comment = { name: name, content: content, pId: parentId ∣∣ null, time: new Date(), } setName("") setContent("") console.log(comment) }

O arquivo Comment.js tem muita coisa acontecendo. Vamos dividi-lo em pedaços menores.

Primeiro, há um componente SingleComment , que renderiza um comentário.

Estou usando a API Adorable para obter um avatar legal. A biblioteca Moment.js é usada para renderizar o tempo em um formato legível.

 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> )

O próximo no arquivo é o componente Comment . Este componente mostra um comentário filho se algum comentário filho foi passado para ele. Caso contrário, ele renderiza uma caixa de resposta, que pode ser ativada e desativada clicando no botão “Responder” ou no botão “Cancelar resposta”.

 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>

Agora que temos uma visão geral, vamos seguir as etapas para fazer nossa seção de comentários.

1. Adicione o Firebase

Primeiro, vamos configurar o Firebase para nosso projeto.

Comece por se inscrever. Acesse o Firebase e inscreva-se em uma conta do Google. Se você não tiver um, clique em “Começar”.

Clique em “Add Project” para adicionar um novo projeto. Adicione um nome para o seu projeto e clique em “Criar um projeto”.

Inicializar o Firebase
(Visualização grande)

Depois de criar um projeto, precisaremos configurar o Cloud Firestore.

No menu do lado esquerdo, clique em “Banco de dados”. Quando uma página for aberta dizendo "Cloud Firestore", clique em "Criar banco de dados" para criar um novo banco de dados do Cloud Firestore.

Cloud Firestore
(Visualização grande)

Quando o pop-up aparecer, escolha “Iniciar no modo de teste”. Em seguida, escolha o local do Cloud Firestore mais próximo de você.

Modo de teste do Firestore
(Visualização grande)

Depois de ver uma página como essa, significa que você criou seu banco de dados do Cloud Firestore com sucesso.

Painel do Firestore
(Visualização grande)

Vamos terminar configurando a lógica para o aplicativo. Volte para o aplicativo e instale o Firebase:

 yarn add firebase

Adicione um novo arquivo, firebase.js , no diretório raiz. Cole este conteúdo nele:

 import firebase from "firebase/app" import "firebase/firestore" var firebaseConfig = 'yourFirebaseConfig' firebase.initializeApp(firebaseConfig) export const firestore = firebase.firestore() export default firebase

Você precisará substituir yourFirebaseConfig pelo do seu projeto. Para encontrá-lo, clique no ícone de engrenagem ao lado de "Visão geral do projeto" no aplicativo Firebase.

Configurações do projeto
(Visualização grande)

Isso abre a página de configurações. Sob o subtítulo do seu aplicativo, clique no ícone da Web, que se parece com isso:

Instalação do projeto
(Visualização grande)

Isso abre um pop-up. No campo "Apelido do aplicativo", digite qualquer nome e clique em "Registrar aplicativo". Isso fornecerá seu objeto 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>

Copie apenas o conteúdo do objeto firebaseConfig e cole-o no arquivo firebase.js .

Tudo bem expor sua chave de API do Firebase?

sim. Conforme declarado por um engenheiro do Google, não há problema em expor sua chave de API.

A única finalidade da chave de API é identificar seu projeto com o banco de dados do Google. Se você definiu regras de segurança rígidas para o Cloud Firestore, não precisa se preocupar se alguém obter sua chave de API.

Falaremos sobre regras de segurança na última seção.

Por enquanto, estamos executando o Firestore no modo de teste, portanto, você não deve revelar a chave da API ao público.

Como usar o Firestore?

Você pode armazenar dados em um dos dois tipos:

  • coleção
    Uma coleção contém documentos. É como um conjunto de documentos.
  • documento
    Um documento contém dados em um par campo-valor.

Lembre-se de que uma coleção pode conter apenas documentos e não outras coleções. Mas um documento pode conter outras coleções.

Isso significa que, se quisermos armazenar uma coleção dentro de uma coleção, armazenaremos a coleção em um documento e armazenaremos esse documento em uma coleção, assim:

 {collection-1}/{document}/{collection-2}

Como estruturar os dados?

O Cloud Firestore é hierárquico por natureza, então as pessoas tendem a armazenar dados assim:

 blog/{blog-post-1}/content/comments/{comment-1}

Mas armazenar dados dessa maneira geralmente apresenta problemas.

Digamos que você queira receber um comentário. Você terá que procurar o comentário armazenado dentro da coleção do blog. Isso tornará seu código mais propenso a erros. Chris Esplin recomenda nunca usar subcoleções.

Eu recomendaria armazenar dados como um objeto achatado:

 blog-posts/{blog-post-1} comments/{comment-1}

Dessa forma, você pode obter e enviar dados facilmente.

Como obter dados do Firestore?

Para obter dados, o Firebase oferece dois métodos:

  • get()
    Isso é para obter o conteúdo uma vez.
  • onSnapshot()
    Esse método envia dados e continua a enviar atualizações, a menos que você cancele a inscrição.

Como enviar dados para o Firestore?

Assim como na obtenção de dados, o Firebase tem dois métodos para salvar dados:

  • set()
    Isso é usado para especificar o ID de um documento.
  • add()
    Isso é usado para criar documentos com IDs automáticos.

Eu sei, isso tem sido muito para entender. Mas não se preocupe, vamos revisitar esses conceitos novamente quando chegarmos ao projeto.

2. Criar Data de Amostra

A próxima etapa é criar alguns dados de amostra para consultarmos. Vamos fazer isso acessando o Firebase.

Acesse o Cloud Firestore. Clique em “Iniciar uma coleção”. Insira comments para o “ID da coleção” e clique em “Avançar”.

Adicionar coleção
(Visualização grande)

Para o "ID do documento", clique em "ID automático. Insira os seguintes dados e clique em “Salvar”.

Adicionar documento
(Visualização grande)

Enquanto você insere os dados, certifique-se de que os “Campos” e “Tipos” correspondem à captura de tela acima. Em seguida, clique em “Salvar”.

É assim que você adiciona um comentário manualmente no Firestore. O processo parece complicado, mas não se preocupe: a partir de agora, nosso aplicativo se encarregará de adicionar comentários.

Neste ponto, nosso banco de dados está assim: comments/{comment} .

3. Obtenha os dados de comentários

Nossos dados de amostra estão prontos para consulta. Vamos começar obtendo os dados para o nosso blog.

Acesse blog-post.js e importe o Firestore do arquivo Firebase que acabamos de criar.

 import {firestore} from "../../firebase.js"

Para consultar, usaremos o hook useEffect do React. Se você ainda não o fez, vamos importá-lo também.

 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])

O método usado para obter dados é onSnapshot . Isso ocorre porque também queremos ouvir as mudanças de estado. Assim, os comentários serão atualizados sem que o usuário precise atualizar o navegador.

Usamos os métodos filter e map para encontrar os comentários cujo slug corresponde ao slug atual.

Uma última coisa que precisamos pensar é a limpeza. Como o onSnapshot continua a enviar atualizações, isso pode causar um vazamento de memória em nosso aplicativo. Felizmente, o Firebase oferece uma boa correção.

 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])

Quando terminar, execute gatsby develop para ver as alterações. Agora podemos ver nossa seção de comentários obtendo dados do Firebase.

Como obter dados do Firestore
(Visualização grande)

Vamos trabalhar no armazenamento dos comentários.

4. Comentários da Loja

Para armazenar comentários, navegue até o arquivo CommentForm.js . Vamos importar o Firestore para este arquivo também.

 import { firestore } from "../../firebase.js"

Para salvar um comentário no Firebase, usaremos o método add() , pois queremos que o Firestore crie documentos com um ID automático.

Vamos fazer isso no método handleCommentSubmission .

 firestore .collection(`comments`) .add(comment) .catch(err => { console.error('error adding comment: ', err) })

Primeiro, obtemos a referência à coleção de comentários e, em seguida, adicionamos o comentário. Também estamos usando o método catch para detectar erros ao adicionar comentários.

Neste ponto, se você abrir um navegador, poderá ver a seção de comentários funcionando. Podemos adicionar novos comentários, bem como postar respostas. O mais incrível é que tudo funciona sem que tenhamos que atualizar a página.

Armazenando comentário
(Visualização grande)

Você também pode verificar o Firestore para ver se ele está armazenando os dados.

Dados armazenados no Firestore
(Visualização grande)

Por fim, vamos falar sobre uma coisa crucial no Firebase: regras de segurança.

5. Apertar as regras de segurança

Até agora, estávamos executando o Cloud Firestore no modo de teste. Isso significa que qualquer pessoa com acesso à URL pode adicionar e ler nosso banco de dados. Isso é assustador.

Para resolver isso, o Firebase nos fornece regras de segurança. Podemos criar um padrão de banco de dados e restringir determinadas atividades no Cloud Firestore.

Além das duas operações básicas (leitura e gravação), o Firebase oferece operações mais granulares: obter, listar, criar, atualizar e excluir.

Uma operação de leitura pode ser dividida como:

  • get
    Obtenha um único documento.
  • list
    Obtenha uma lista de documentos ou uma coleção.

Uma operação de gravação pode ser dividida como:

  • create
    Crie um novo documento.
  • update
    Atualizar um documento existente.
  • delete
    Excluir um documento.

Para proteger o aplicativo, volte para o Cloud Firestore. Em "Regras", digite isto:

 service cloud.firestore { match /databases/{database}/documents { match /comments/{id=**} { allow read, create; } } }

Na primeira linha, definimos o serviço, que no nosso caso é o Firestore. As próximas linhas informam ao Firebase que qualquer coisa dentro da coleção de comments pode ser lida e criada.

Se tivéssemos usado isso:

 allow read, write;

… isso significaria que os usuários poderiam atualizar e excluir comentários existentes, o que não queremos.

As regras de segurança do Firebase são extremamente poderosas, permitindo restringir determinados dados, atividades e até mesmo usuários.

Para construir sua própria seção de comentários

Parabéns! Você acabou de ver o poder do Firebase. É uma excelente ferramenta para construir aplicativos seguros e rápidos.

Criamos uma seção de comentários supersimples. Mas nada impede você de explorar outras possibilidades:

  • Adicione fotos de perfil e armazene-as no Cloud Storage para Firebase;
  • Use o Firebase para permitir que os usuários criem uma conta e os autentique usando a autenticação do Firebase;
  • Use o Firebase para criar comentários in-line do tipo Medium.

Uma ótima maneira de começar seria acessar a documentação do Firestore.

Por fim, vamos para a seção de comentários abaixo e discutir sua experiência com a criação de uma seção de comentários usando o Firebase.

The Smashing Cat explorando novos insights, nos Smashing Workshops, é claro.

Bits úteis de front-end e UX, entregues uma vez por semana.

Com ferramentas para ajudá-lo a fazer seu trabalho melhor. Assine e receba o PDF das listas de verificação de design de interface inteligente da Vitaly por e-mail.

No front-end e UX. Confiado por 190.000 pessoas.