---
title: "为 Docusaurus 博客页面添加评论区"
description: "使用 Docusaurus 的 Swizzle 功能，向 Docusaurus 博客页面添加 Giscus 评论区"
author: "xyspg"
lang: "zh"
published: "2023-02-19T13:30:00.000Z"
tags:
  - "中文"
url: "https://xyspg.moe/blog/add-comment-section-to-docusaurus"
image: "https://xyspg.moe/images/blog/69a2996aee7927fa94389f287408c1060b2b88e3-3826x2065.png"
translations:
  en: "https://xyspg.moe/blog/en/add-comment-section-to-docusaurus"
  ja: "https://xyspg.moe/blog/ja/add-comment-section-to-docusaurus"
---

# 为 Docusaurus 博客页面添加评论区

## 原理

Docusaurus 官方并没有提供开箱即用的评论区组件，但是我们可以通过 [Swizzle](https://docusaurus.io/zh-CN/docs/swizzling) 功能来实现组件的自定义。

本文使用的评论系统是 [Giscus](https://giscus.app/zh-CN)，这是一款基于 GitHub Discussions 的开源评论系统。

![Image](https://xyspg.moe/images/blog/707ea9c00131890700239e3790dad15591b0a798-1526x476.png)

## 创建 Giscus 配置

### 仓库配置

在 [GitHub](https://github.com/) 转到你 Docusaurus 网站的仓库页面，确保仓库已经公开。

如未公开，可以转到 Settings - General 最底部 Danger Zone - Change repository visibility。

确认仓库处于公开情况之后，在 Settings 的 Features 选项卡中勾选 Discussions

![Image](https://xyspg.moe/images/blog/3bf4d985c3891b5c8c8fd8f6064f992c6fa72c4d-1262x132.png)

转到 [Giscus GitHub App 页面](https://github.com/apps/giscus)，按照提示安装。根据自身需求选择 Repository access 范围。

### 获取 Giscus 配置

打开 [Giscus 官网](https://giscus.app/zh-CN)，输入自己的仓库地址

![Image](https://xyspg.moe/images/blog/441d939dbd9a4ab9c4ef934e1453d616a5b34b45-1032x578.png)

在 “Discussion 分类”中选择“📣 Announcements”，剩下的选项可按需配置。 完成配置后，可以得到底部的配置文件。

```javascript
<script
  src="https://giscus.app/client.js"
  data-repo="your-name/your-repo"
  data-repo-id="your-repo-id"
  data-category="Announcements"
  data-category-id="your-category-id"
  data-mapping="pathname"
  data-strict="0"
  data-reactions-enabled="1"
  data-emit-metadata="0"
  data-input-position="bottom"
  data-theme="preferred_color_scheme"
  data-lang="zh-CN"
  crossorigin="anonymous"
  async
/>
```

## 通过 Swizzle 插入 Giscus 组件

首先在项目中安装 Giscus React 组件

`npm i @giscus/react`

在 `/src/components/`下创建 `GiscusComponent.js` 文件

复制进以下代码，对应的 id 值可从上文的配置文件中寻找：

```javascript
// GiscusComponent.js
import React from "react";
import Giscus from "@giscus/react";
import { useColorMode } from "@docusaurus/theme-common";

export default function GiscusComponent() {
  const { colorMode } = useColorMode();

  return (
    <Giscus
      repo="" //这里填写你的repo
      repoId="" //你的repo id
      category=" " //你的category（默认 Announcement）
      categoryId="" //你的category id
      mapping="pathname"
      term="Welcome to @giscus/react component!"
      strict="0"
      reactionsEnabled="1"
      emitMetadata="1"
      inputPosition="top"
      theme={colorMode}
      lang="zh-CN"
      loading="lazy"
      crossorigin="anonymous"
      async
    />
  );
}
```

运行 Swizzle

`npm run swizzle`

选择你的主题配置文件（默认为 theme-classic)

```sh
> docusaurus swizzle

? Select a theme to swizzle: › - Use arrow-keys. Return to submit.
❯   @docusaurus/theme-classic
    @docusaurus/plugin-debug
    [Exit]
```

向下找到 `BlogPostItem`，回车确认

```sh
BlogListPage (Unsafe)
    BlogListPaginator (Unsafe)
❯   BlogPostItem (Unsafe)
    BlogPostItem/Container (Unsafe)
    BlogPostItem/Content (Unsafe)
```

回车选择 `Wrap` 和 `YES: I know what I am doing!`

```sh
? Which swizzle action do you want to do? › - Use arrow-keys. Return to submit.
❯   Wrap (Unsafe)
    Eject (Unsafe)
    [Exit]
```

打开 `/src/theme/BlogPostItem/index.js`，将内容修改为

```javascript
// src/theme/BlogPostItem/index.js
import React from "react";
import { useBlogPost } from "@docusaurus/theme-common/internal";
import BlogPostItem from "@theme-original/BlogPostItem";
import GiscusComponent from "@site/src/components/GiscusComponent";
import useIsBrowser from "@docusaurus/useIsBrowser";

export default function BlogPostItemWrapper(props) {
  const { metadata } = useBlogPost();
  const isBrowser = useIsBrowser();

  const { frontMatter, slug, title } = metadata;
  const { enableComments } = frontMatter;

  // 防止 ReferenceError: window is not defined 错误 (https://docusaurus.io/docs/advanced/ssg)
  var isCurrentUrlBlog = false;
  if (isBrowser) {
    isCurrentUrlBlog = window.location.pathname === "/blog";
  }

  return (
    <>
      <BlogPostItem {...props} />
      {enableComments && !isCurrentUrlBlog && <GiscusComponent />}
    </>
  );
}
```

接下来，在对应的 Blog 页面头部元数据中加入`enableComments: true` 例如：

```markdown
---
title: 一个标题
authors: 作者
tags: [标签]
enableComments: true
---
```

如果重新运行 swizzle，组件会被还原，需要重新修改
