通过firebase搭建一个评论系统, part 1

November 17, 2020 ... ☕️ 4 min read

随着评论习惯慢慢改变,之前如火如荼的博客慢慢消沉下去了,随之慢慢冷淡下去的是博客连接起来的评论圈子,例如在各个博客下面留言“混个脸熟”,还有通过评论来推广链接等做法,也慢慢淡出我们的视线。

于是,很多博客,尤其是静态博客,要么直接内嵌基于github的comments,第三方disqus或者是直接没有评论。评论虽然不是必需品,但是作为一个blog,一个适当的评论模块当然是锦上添花。

之前使用了disqus,但是载入一堆js,而且样式还只能魔改,对于有些强迫症的朋友不太友好。所以自建一套评论系统便一直萦绕在脑袋里。

首先是数据保存,办法一般是在github上存储,或者使用数据库。如果不想架vps,那就要使用第三方数据库服务了。

具体步骤,我是参考的这篇 How To Build Your Own Comment System Using Firebase

实现步骤

确定唯一标识

使用过disqus的知道,它的config需要几个字段:identifier、url、title,其中identifier是文章的唯一标识,既然通过这个唯一标识能建立数据库到文章的连接,那么自己建立一个数据库,然后打开文章的时候,单独操作相关数据就可以了。

这个标识可以是文章id,或者设置的链接名(通常是英文)。

申请并配置firebase

这个推荐参考官方文档,或上面提供的链接。根据实际需要,可以考虑使用实时数据库或者firestore。

代码部分

firebase提供了npm包,这个sdk可以直接引入项目中使用。基本步骤是通过config初始化firebase,利用api来读写数据。

初始化:

import firebase from 'firebase/app';
import 'firebase/database';

const firebaseConfig = {
  apiKey: 'key',
  appId: 'key',
  authDomain: 'key',
  databaseURL: 'key',
  measurementId: 'key',
  messagingSenderId: 'key',
  projectId: 'key',
  storageBucket: 'key',
};
firebase.initializeApp(firebaseConfig);

const db = firebase.database();

// 检测连接状态
export const connectedRef = db.ref('.info/connected');

const firebaseRef = db.ref(`/comments`);

数据读取:

// 通过缩略名获取评论
const getCommentsByPostSlug = (slug) => {
  return new Promise((resolve, reject) => {
    firebaseRef
      .orderByChild('slug')
      .equalTo(slug)
      .once('value', (snapshot) => {
        const comments = (snapshot.val());
        resolve(comments || []);
      });
  });
};

数据写入:

// comment写入
const addComment = (comment, callback) => {
  if (!comment.valid) {
    comment.valid = location.host;
  }
    const id = firebaseRef.push().key;
    return db.ref(`/comments/${id}`).set({...comment });
};

数据监听:

const addCommentsChangeListener = (slug, callback) => {
  firebaseRef.on('value', (snapshot) => {
    const posts = snapshot.val();
    callback(posts);
  });
};

渲染部分:

const BlogCommentsTemplate = (props) => {
  const [comments, setComments] = useState(null);
  useEffect(() => {
    // 获取评论
    getCommentsByPostSlug(slug).then((items) => {
      setComments(items);
    });
    // 监听评论变化
    addCommentsChangeListener(slug, (items) => {
      setComments(items);
    });
  }, [slug]);
  // 渲染评论内容
  return (<Comments comments={comments} />);

实例

可以在这篇文章下面评论,目前支持一级嵌套,仅可回复楼主,样式也和wordpress类似。

安全性

对应完全暴露在网络上的数据库,安全性是首先要考虑的,通常,可以在服务器端通过验证来源网站、约定token等方法,规避一些风险。对于firebase也类似,这部分请参考 Firebase 发布核对清单

对于网页应用:

1、(设置完没什么用,可能需要开登录)为您的网域添加白名单,以防止未经授权的使用: 请前往 https://console.developers.google.com/apis, 在凭据(credentials)下,设置API对应的安全域名
2、配置合适的数据库读写规则,防止意外操作
3、考虑使用身份验证

参考文档

1、数据库规则
2、避免不安全的规则
3、实时数据库的读写操作
4、用firebase建立评论系统

#react

SideEffect is a blog for front-end web development.
Code by Axiu / rss