如何使用 Firebase 構建自己的評論系統
已發表: 2022-03-10評論部分是為您的博客建立社區的好方法。 最近開始寫博客的時候,我想添加一個評論部分。 然而,這並不容易。 託管評論系統,例如 Disqus 和 Commento,都有自己的一系列問題:
- 他們擁有您的數據。
- 他們不是免費的。
- 您不能對它們進行太多自定義。
所以,我決定建立自己的評論系統。 Firebase 似乎是運行後端服務器的完美託管替代方案。
首先,您可以獲得擁有自己的數據庫的所有好處:您可以控制數據,並且可以根據需要對其進行結構化。 其次,您不需要設置後端服務器。 您可以從前端輕鬆控制它。 這就像兩全其美:一個沒有後端麻煩的託管系統。
在這篇文章中,這就是我們要做的。 我們將學習如何使用靜態站點生成器 Gatsby 設置 Firebase。 但是這些原理可以應用於任何靜態站點生成器。
讓我們潛入吧!
什麼是 Firebase?
Firebase 是一種後端即服務,它為應用程序開發人員提供工具,例如數據庫、託管、雲功能、身份驗證、分析和存儲。
Cloud Firestore(Firebase 的數據庫)是我們將用於此項目的功能。 它是一個 NoSQL 數據庫。 這意味著它的結構不像具有行、列和表的 SQL 數據庫。 您可以將其視為一棵大型 JSON 樹。
項目介紹
讓我們通過從 GitHub 克隆或下載存儲庫來初始化項目。
我為每個步驟創建了兩個分支(一個在開頭,一個在結尾),以便您更輕鬆地跟踪我們進行的更改。
讓我們使用以下命令運行項目:
gatsby develop
如果您在瀏覽器中打開該項目,您將看到一個基本博客的基本內容。
評論部分不工作。 它只是加載一個示例評論,並且在提交評論後,它將詳細信息記錄到控制台。
我們的主要任務是讓評論部分正常工作。
評論部分的工作原理
在做任何事情之前,讓我們了解一下註釋部分的代碼是如何工作的。
四個組件正在處理評論部分:
-
blog-post.js
-
Comments.js
-
CommentForm.js
-
Comment.js
首先,我們需要識別帖子的評論。 這可以通過為每篇博客文章創建一個唯一的 ID 來完成,或者我們可以使用 slug,它始終是唯一的。
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,並註冊一個 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 應用程序中“項目概述”旁邊的齒輪圖標。
這將打開設置頁面。 在您的應用程序的副標題下,單擊 Web 圖標,如下所示:
這將打開一個彈出窗口。 在“應用暱稱”字段中,輸入任意名稱,然後單擊“註冊應用”。 這會給你的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}
但是以這種方式存儲數據往往會帶來問題。
說你想得到評論。 您必須查找存儲在博客集合深處的評論。 這將使您的代碼更容易出錯。 Chris Esplin 建議永遠不要使用子集合。
我建議將數據存儲為扁平對象:
blog-posts/{blog-post-1} comments/{comment-1}
這樣,您可以輕鬆獲取和發送數據。
如何從 Firestore 獲取數據?
為了獲取數據,Firebase 為您提供了兩種方法:
-
get()
這是為了獲取內容一次。 -
onSnapshot()
此方法會向您發送數據,然後繼續發送更新,除非您取消訂閱。
如何將數據發送到 Firestore?
就像獲取數據一樣,Firebase 有兩種保存數據的方法:
-
set()
這用於指定文檔的 ID。 -
add()
這用於創建具有自動 ID 的文檔。
我知道,這需要掌握很多。 但別擔心,當我們到達項目時,我們會再次重新審視這些概念。
2. 創建樣品日期
下一步是創建一些示例數據供我們查詢。 讓我們通過 Firebase 來做到這一點。
轉到 Cloud Firestore。 點擊“開始收藏”。 為“集合 ID”輸入comments
,然後單擊“下一步”。
對於“文檔 ID”,單擊“自動 ID。 輸入以下數據,然後單擊“保存”。
輸入數據時,請確保“字段”和“類型”與上面的屏幕截圖相匹配。 然後,單擊“保存”。
這就是您在 Firestore 中手動添加評論的方式。 這個過程看起來很麻煩,但不用擔心:從現在開始,我們的應用將負責添加評論。
此時,我們的數據庫如下所示: comments/{comment}
。
3. 獲取評論數據
我們的示例數據已準備好進行查詢。 讓我們從獲取我們博客的數據開始。
轉到blog-post.js
,然後從我們剛剛創建的 Firebase 文件中導入 Firestore。
import {firestore} from "../../firebase.js"
要查詢,我們將使用 React 中的useEffect
鉤子。 如果你還沒有,讓我們也導入它。
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
方法來查找其 slug 與當前 slug 匹配的評論。
我們需要考慮的最後一件事是清理。 因為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 創建具有自動 ID 的文檔。
讓我們在handleCommentSubmission
方法中這樣做。
firestore .collection(`comments`) .add(comment) .catch(err => { console.error('error adding comment: ', err) })
首先,我們獲取到comments 集合的引用,然後添加comment。 我們還使用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 創建類似於 Medium 的內聯評論。
一個很好的開始方法是查看 Firestore 的文檔。
最後,讓我們轉到下面的評論部分,討論您使用 Firebase 構建評論部分的經驗。
有用的前端和用戶體驗位,每週交付一次。
借助工具幫助您更好地完成工作。 通過電子郵件訂閱並獲取 Vitaly 的智能界面設計清單 PDF 。
在前端和用戶體驗上。 受到 190.000 人的信賴。