Skip to content
Shaoheng Nie
Go back

如何在 AstroPaper 中集成 Giscus 评论

Updated:

GitHub Pages 等平台上托管轻量静态博客有许多优点,但也会牺牲一些交互性。幸运的是,Giscus 的出现为在静态网站上嵌入用户评论提供了一种方式。

目录

Giscus 的工作原理

Giscus 使用 GitHub API 来读取和存储 GitHub 用户在仓库关联的 Discussions 中发表的评论。

Giscus 客户端脚本包嵌入你的网站,使用正确的仓库 URL 进行配置,用户就可以查看和撰写评论(需登录 GitHub)。

这种方式是无服务器的,因为评论存储在 GitHub 上并在客户端动态加载,因此非常适合像 AstroPaper 这样的静态博客。

设置 Giscus

Giscus 可以在 giscus.app 上轻松设置,但我还是会简要概述一下过程。

前提条件

Giscus 正常工作的前提条件是:

如果由于任何原因无法满足其中任何条件,那么很遗憾,Giscus 将无法集成。

配置 Giscus

接下来需要配置 Giscus。在大多数情况下,预选的默认值都是合适的,只有在你出于特定原因且清楚自己在做什么时才应修改它们。不必过于担心做出错误的选择;你随时可以调整配置。

但是你需要:

配置好设置后,Giscus 会为你生成一个 <script> 标签,你将在后续步骤中使用它。

简单的脚本标签

你现在应该有一个类似这样的 script 标签:

<script
  src="https://giscus.app/client.js"
  data-repo="[ENTER REPO HERE]"
  data-repo-id="[ENTER REPO ID HERE]"
  data-category="[ENTER CATEGORY NAME HERE]"
  data-category-id="[ENTER CATEGORY ID HERE]"
  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="en"
  crossorigin="anonymous"
  async
></script>

只需将其添加到网站的源代码中。如果你正在使用 AstroPaper 并希望启用文章评论,导航到 PostDetails.astro 并将其粘贴到你希望评论出现的位置,比如「分享这篇文章:」按钮下方。

<Layout {...layoutProps}>
  <main>
    <ShareLinks />

    <script
      src="https://giscus.app/client.js"
      data-repo="[ENTER REPO HERE]"
      data-repo-id="[ENTER REPO ID HERE]"
      data-category="[ENTER CATEGORY NAME HERE]"
      data-category-id="[ENTER CATEGORY ID HERE]"></script>
  </main>
  <Footer />
</Layout>src/layouts/PostDetails.astro

大功告成!你已经成功在 AstroPaper 中集成了评论功能!

支持亮色/暗色主题的 React 组件

嵌入在布局中的 script 标签是相当静态的,Giscus 配置(包括 theme)被硬编码在布局中。考虑到 AstroPaper 具有亮色/暗色主题切换功能,评论能随网站其他部分无缝地在亮色和暗色主题之间切换会更好。要实现这一点,需要一种更复杂的方式来嵌入 Giscus

首先,我们要安装 GiscusReact 组件

npm i @giscus/react && npx astro add react

然后在 src/components 中创建一个新的 Comments.tsx React 组件:

import Giscus, { type Theme } from "@giscus/react";
import { GISCUS } from "@/constants";
import { useEffect, useState } from "react";

interface CommentsProps {
  lightTheme?: Theme;
  darkTheme?: Theme;
}

export default function Comments({
  lightTheme = "light",
  darkTheme = "dark",
}: CommentsProps) {
  const [theme, setTheme] = useState(() => {
    const currentTheme = localStorage.getItem("theme");
    const browserTheme = window.matchMedia("(prefers-color-scheme: dark)")
      .matches
      ? "dark"
      : "light";

    return currentTheme || browserTheme;
  });

  useEffect(() => {
    const mediaQuery = window.matchMedia("(prefers-color-scheme: dark)");
    const handleChange = ({ matches }: MediaQueryListEvent) => {
      setTheme(matches ? "dark" : "light");
    };

    mediaQuery.addEventListener("change", handleChange);

    return () => mediaQuery.removeEventListener("change", handleChange);
  }, []);

  useEffect(() => {
    const themeButton = document.querySelector("#theme-btn");
    const handleClick = () => {
      setTheme(prevTheme => (prevTheme === "dark" ? "light" : "dark"));
    };

    themeButton?.addEventListener("click", handleClick);

    return () => themeButton?.removeEventListener("click", handleClick);
  }, []);

  return (
    <div className="mt-8">
      <Giscus theme={theme === "light" ? lightTheme : darkTheme} {...GISCUS} />
    </div>
  );
}src/components/Comments.tsx

这个 React 组件不仅封装了原生的 Giscus 组件,还引入了额外的 props,即 lightThemedarkTheme。利用两个事件监听器,Giscus 评论将与网站主题保持一致,在网站或浏览器主题变化时动态切换暗色和亮色主题。

我们还需要定义 GISCUS 配置,最佳位置是 constants.ts

import type { GiscusProps } from "@giscus/react";

...

export const GISCUS: GiscusProps = {
  repo: "[ENTER REPO HERE]",
  repoId: "[ENTER REPO ID HERE]",
  category: "[ENTER CATEGORY NAME HERE]",
  categoryId: "[ENTER CATEGORY ID HERE]",
  mapping: "pathname",
  reactionsEnabled: "0",
  emitMetadata: "0",
  inputPosition: "bottom",
  lang: "en",
  loading: "lazy",
};src/constants.ts

请注意,在这里指定 theme 将覆盖 lightThemedarkTheme props,导致主题设置变为静态,类似于之前使用 <script> 标签嵌入 Giscus 的方式。

要完成整个过程,将新的 Comments 组件添加到 PostDetails.astro 中(替换上一步的 script 标签)。

import Comments from "@/components/Comments";

<ShareLinks />

<Comments client:only="react" />

<hr class="my-6 border-dashed" />

<Footer />src/layouts/PostDetails.astro

就这样!


Share this post on:

Previous Post
AstroPaper 博客文章中的动态 OG 图片生成
Next Post
如何使用 Git Hooks 设置创建日期和修改日期