跳到主要内容

评论系统

评论系统可以说一直是静态博客的一大痛点。国内的很多评论系统不太稳定,要么是作者不再维护,要么是项目关闭;而国外的评论系统要么加载慢,要么收费贵。本来觉得网站访问量少,可以不用评论系统,或者直接通过邮件交流也行。但一段时间后觉得评论系统还是有必要的:

  1. 我希望读者读完文章后,能提出自己的疑问或质疑、指出文章的谬误之处等,即希望与读者进行有价值的沟通;
  2. 基于第一点,我希望这些有价值的内容能让更多有类似疑问的人看到。

基于上述原因,还是又考查了一些评论系统,如下:

  • Disqus: 可以说是目前最流行的评论托管服务,但据说有些隐私、安全问题,另外对于国内用户而言,还存在加载慢等问题。
  • Remark42: 支持 Markdown,更新较频繁,DEMO
  • Cusdis: 轻量级评论系统,使用简单: 轻量级评论系统,使用也很方便。
  • Utterances: 建立在 GitHub issues 上的轻量级评论工具。
  • Giscus: 受 Utterances 启动,基于 GitHub Discussions 驱动的评论系统。
  • Gittalk: 基于 Github Issue 和 Preact 开发的评论插件,不过看仓库截至目前已经快一年未更新了。
  • Livere: 支持多种 SNS 账号登录,功能上来讲还错,不过国内用户使用仍有一点慢。
  • Waline: 基于 Valine 衍生的简洁、安全的评论系统。

在经过一番比较后,决定使用 Waline。配置过程如下:

LeanCloud 设置

  1. 打开 LeanCloud,选择国际版(若选国内版本的话,会要求实名认证、域名备案等信息)进行注册,完成邮箱验证和手机号验证。
  2. 点击左上角的应用/查看所有应用,点击创建应用,填写应用名称后,点击创建。
  3. 进入刚创建的应用,点击设置/应用凭证,可以看到 APP ID、APP Key 和 Master Key 信息。

Vercel 部署

  1. 使用 Github 账户登录 Vercel
  2. 为 Vercel 授权后,创建 git 仓库,一两分钟后创建成功,点击 Go to Dashboard 跳转到项目页面,此时 Github 也会有 Vercel 基于 Waline 模板初始化的仓库。
  3. 点击顶部的 Settings/Environment Variables,配置三个环境变量 LEAN_ID, LEAN_KEYLEAN_MASTER_KEY,分别对应上一步 LeanCloud 的三个变量:
  4. 配置完成后,点击顶部的 Deployments,点击项目右侧的 Redeploy 来重新部署项目。
  5. 跳转到 Overview 后,等待片刻后 STATUS 会变成 Ready,点击 Visit 即跳转到服务端地址,可以测试发送评论试试!
  6. 点击 Settings/Domains,添加网站评论的域名(如 c.qileq.com),然后在域名提供商中增加该 DNS 记录,记录类型为 CNAME,记录值为 cname.vercel-dns.com。添加成功后,通过评论域名后即能通过自己的域名来管理评论了:
    • 评论系统:c.qileq.com
    • 评论管理:c.qileq.com/ui
  7. 访问 c.qileq.com/ui/register 注册管理员,成功后点击左上角的管理/评论,即可以管理评论了。

开启 Waline

上面的准备工作做完后,就可以在文章中开启评论了,不过目前得在每篇文章中都加 Waline 的设置。想想都觉得麻烦。笔者想在 blog 和 doc 页面自动显示评论区,但对于部分不想开启评论的文章,则不显示,如何做到呢?且见下文步骤:

创建评论组件

src/components 目录下创建 Comment.js,内容如下:

src/components/Comment.js
import React, { PureComponent } from 'react';

export default class Comment extends PureComponent {
constructor(props) {
super(props)
this._commentRef = React.createRef()
}

async componentDidMount() {
if (typeof window === "undefined") {
return
}
if(!this._commentRef.current) {
return
}
const Waline= await(await import('@waline/client')).default
this.Waline = new Waline({
el: this._commentRef.current,
serverURL: 'https://c.qileq.com',
visitor: true, // 开启阅读量统计
path: this.props.id,
})
}

render() {
return <div className="comment-area" ref={this._commentRef} />
}
}

其中 serverURL 值为自己网站评论系统的域名。

修改 Blog 页面

可以通过 Docusaurus 提供的 Swizzling 功能来修改界面显示,其分为两种类型:

  1. Ejecting:拷贝指定的默认组件,用户可修改(增改删均可)组件的任一部分,修改完成后会代替默认组件展示。
  2. Wrapping:围绕默认组件创建一个 wrapper,其不会改变默认组件的行为,只能增强页面的显示。

两者相当于整容和化妆的区别,前者可修改默认组件内容,难度高;后者在默认组件周围增加一层代码包裹,简单。

尝试 npm run swizzle @docusaurus/theme-classic BlogPostItem -- --wrap 来 wrap BlogPostItem,结果评论在 blog 首页跟着文章简要一起展示了,应该通过 eject 的方式来修改。笔者想让评论区在翻页组件后显示,于是修改 BlogPostPage

npm run swizzle @docusaurus/theme-classic BlogPostPage -- --eject

选择 YES: I know what I am doing!,然后编辑 src/theme/BlogPostPage/index.js,做如下修改:

src/theme/BlogPostPage/index.js
...
import BlogPostPageMetadata from '@theme/BlogPostPage/Metadata';
import TOC from '@theme/TOC';
+ import Comment from '@site/src/components/Comment';

...
function BlogPostPageContent({sidebar, children}) {
const {metadata, toc} = useBlogPost();
const {nextItem, prevItem, frontMatter} = metadata;
const {
hide_table_of_contents: hideTableOfContents,
toc_min_heading_level: tocMinHeadingLevel,
toc_max_heading_level: tocMaxHeadingLevel,
+ comments = true,
} = frontMatter;
return (
<BlogLayout
...

{(nextItem || prevItem) && (
<BlogPostPaginator nextItem={nextItem} prevItem={prevItem} />
)}

+ {comments && (<Comment id={children.slug} />)}
</BlogLayout>
);

注意,上面在 frontMatter 中添加了自定义变量 comments,默认值为 true,即默认展示评论。若不希望展示评论,则在博客元数据区域将 comments 设置为 false,如:

---
slug: cate/test-comments
title: Some title
comments: false
---
提示

由于 Docusaurus 仍在更新中,组件代码仍在变化中,若需要修改的部分与上述不一致,可执行 npm run swizzle -- --list 来查看组件,根据自己需求进行调整。

修改 Doc 页面

如果 Doc 也需要添加评论的话,过程和 Blog 有类似。

执行 npm run swizzle @docusaurus/theme-classic DocItem/Layout -- --eject,修改 src/theme/DocItem/Layout/index.js,如下:

src/theme/DocItem/Layout/index.js
...
import DocItemContent from '@theme/DocItem/Content';
import DocBreadcrumbs from '@theme/DocBreadcrumbs';
import styles from './styles.module.css';
+ import Comment from '@site/src/components/Comment';

function useDocTOC() {
...
const desktop =
canRender && (windowSize === 'desktop' || windowSize === 'ssr') ? (
<DocItemTOCDesktop />
) : undefined;
+ const comments = frontMatter.comments == undefined ? true : frontMatter.comments;
return {
hidden,
mobile,
desktop,
+ comments,
};
}

export default function DocItemLayout({children}) {
</article>
<DocItemPaginator />
+ {docTOC.comments && (<Comment id={children.id} />)}
</div>
</div>
...

修改 CSS

若需要修改评论区样式,则在 src/css/custom.scss 修改,如下:

src/css/custom.scss
.comment-area {
margin: 2em 0;

.v[data-class=v] {
.vcomment .vpanel, .vcount {
margin: 0;
padding: 0;
}
}
}

一切完成后,重启应用,查看是否成功吧!

展示阅读量

Valine 提供了统计文章阅读量的功能。开启过程很简单。

  1. 初始化 Valine 时设置 visitor: true 开启阅读量统计(见创建评论组件)。Valine 会自动在 leancloud 应用创建 Counter 类来统计页面打开次数。

  2. 在文章适当位置添加如下代码展示阅读量:

    <!-- id 将作为查询条件 -->
    <span id="<Your/Path/Name>" class="leancloud_visitors" data-flag-title="Your Article Title">
    <em class="post-meta-item-text">阅读量: </em>
    <i class="leancloud-visitors-count"></i>
    </span>

    读者只需将上面的 id 值修改为当前页面的 url 地址,如本页地址为 https://qileq.com/about/site/remark ,则设置 id 值为 /about/site/remark,Valine 将根据该 id 查询 leanCloud 应用中 Counter 类的 url 字段,返回 time 值并插入到 css class 名为 leancloud-visitors-count 的子元素中。

这种方式根据请求 Valine 的次数来记录点击量,因此即使本地测试打开页面,也会纳入到线上对应页面的阅读量统计中。