docusaurus 增加评论系统
背景
像docusaurus这种静态网站本身是没有自带评论系统的,但是我们可以使用第三方的giscus增加。 先看下实现的效果如下:
和整体网页能够保持统一,且打开网页时候会自动进行加载,也可以配置为懒加载。
使用giscus
以下内容出自博客在 Docusaurus 中添加评论系统
先决条件
- 你的项目运行 Docusaurus,至少有一篇博文或文档
- 你安装的主题是
theme classic
,也是默认的。 - 根据对应的评论插件注册一下拿到配置
配置 giscus
先登录你的github账号安装 giscus 应用 giscus app
进到giscus的官网配置好语言、评论要发到的github仓库、页面与映射关系, 选择一个discussion分类、主题等。
配置的时候注意看这三点
启用Discussions在仓库的Setting中可以找到
页面 ↔️ discussion 映射关系 一般选择Pathname就行。实际生成的评论的时候,会以你的博客请求 路径创建一个类似话题的讨论。
拿到配置好的 <script>
标签, 类似:
<script src="https://giscus.app/client.js"
data-repo="xxxxx"
data-repo-id="xxxx"
data-category="xxxx"
data-category-id="xxxxx"
data-mapping="pathname"
data-reactions-enabled="1"
data-emit-metadata="0"
data-input-position="bottom"
data-theme="light"
data-lang="zh-CN"
crossorigin="anonymous"
async>
在你的 Docusaurus 项目根目录执行
yarn swizzle @docusaurus/theme-classic BlogPostPage
选择 Eject (Unsafe)
回车
选择 YES: I know what I am doing!
回车
这时你的项目目录下src/theme/BlogPostPage
生成了自定义主题的文件
注意:这里生成的文件只对你的Blog目录下的文章插入评论系统 如果你要在docs目录下也插入评论系统,则还需要执行命令:
yarn swizzle @docusaurus/theme-classic DocItem/Layout
下一步修改文件
下面三处标注是我们要修改添加代码的地方。 注意版本不同配置可能存在差异 根据标注自己找放评论的位置。
改动文件为:src/theme/BlogPostPage/index.js
//开始1
import React, { useEffect, useRef } from 'react';
//结束1
import clsx from 'clsx';
import {HtmlClassNameProvider, ThemeClassNames} from '@docusaurus/theme-common';
import {BlogPostProvider, useBlogPost} from '@docusaurus/theme-common/internal';
import BlogLayout from '@theme/BlogLayout';
import BlogPostItem from '@theme/BlogPostItem';
import BlogPostPaginator from '@theme/BlogPostPaginator';
import BlogPostPageMetadata from '@theme/BlogPostPage/Metadata';
import TOC from '@theme/TOC';
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,
} = frontMatter;
//开始2
const commentElement = useRef(null);
useEffect(() => {
// Update the document title using the browser API
let s = document.createElement("script");
s.src = "https://giscus.app/client.js";
s.setAttribute("data-repo", "[你的仓库]");
s.setAttribute("data-repo-id", "[你的仓库 ID]=");
s.setAttribute("data-category", "[你的分类名]");
s.setAttribute("data-category-id", "[你的分类 ID]");
s.setAttribute("data-mapping", "pathname");
s.setAttribute("data-reactions-enabled", "1");
s.setAttribute("data-emit-metadata", "0");
s.setAttribute("data-input-position", "bottom");
s.setAttribute("data-theme", "light");
s.setAttribute("data-lang", "zh-CN");
s.setAttribute("crossorigin", "anonymous");
s.async = true;
commentElement.current.appendChild(s);
}, []);
//结束2
return (
<BlogLayout
sidebar={sidebar}
toc={
!hideTableOfContents && toc.length > 0 ? (
<TOC
toc={toc}
minHeadingLevel={tocMinHeadingLevel}
maxHeadingLevel={tocMaxHeadingLevel}
/>
) : undefined
}>
<BlogPostItem>{children}</BlogPostItem>
{(nextItem || prevItem) && (
<BlogPostPaginator nextItem={nextItem} prevItem={prevItem} />
)}
//开始3
<div style={{marginTop:'20px'}} ref={commentElement}></div>
//结束3
</BlogLayout>
);
}
export default function BlogPostPage(props) {
const BlogPostContent = props.content;
return (
<BlogPostProvider content={props.content} isBlogPostPage>
<HtmlClassNameProvider
className={clsx(
ThemeClassNames.wrapper.blogPages,
ThemeClassNames.page.blogPostPage,
)}>
<BlogPostPageMetadata />
<BlogPostPageContent sidebar={props.sidebar}>
<BlogPostContent />
</BlogPostPageContent>
</HtmlClassNameProvider>
</BlogPostProvider>
);
}