Next.js 博客接入 giscus 评论完整教程

ShuaiQi
#建站#giscus#评论系统

静态博客最麻烦的一块就是评论:没有后端、没有数据库,传统的评论系统要么收费,要么需要自建服务。giscus 用 GitHub Discussions 存评论,纯前端接入,免费且没有广告,是目前个人博客最省心的方案之一。

这篇文章记录本站接入 giscus 的完整过程,照着做大概十几分钟能跑起来。

为什么选 giscus

对比几个常见方案:

方案成本数据存放是否需要后端
giscus免费自己的 GitHub 仓库不需要
Disqus免费但带广告第三方不需要
Valine / Waline需自建或付费托管自己的数据库需要
自研评论免费自己的数据库需要

如果你的博客源码本来就在 GitHub,giscus 几乎没有迁移成本,评论和代码在同一个账号体系下管理。

第一步:创建评论仓库

新建一个公开仓库专门存评论,不要和博客源码混在一起:

  1. 在 GitHub 新建仓库,例如 yourname/blog-comments
  2. 必须是 public,私有仓库 giscus 读不到
  3. 进入仓库 Settings,勾选 Discussions 功能

仓库本身可以先留空,giscus 会在第一次有人评论时自动创建对应的 Discussion。

第二步:安装 giscus App

打开 GitHub Apps - giscus,点击 Install,选择刚创建的评论仓库授权。如果只授权单个仓库,记得在安装页里选中它。

第三步:生成配置

打开 giscus.app,输入仓库名,它会实时校验并给出 <script> 配置。几个关键选项:

  • 映射关系(mapping):选 pathname,按页面路径匹配,同一篇文章不同域名也能对上
  • Discussion 分类:选 General 或 Announcements,建议单独建一个 Comments 分类,只搜索该分类
  • 输入框位置:放评论上方还是下方,看个人习惯
  • 懒加载:建议开启,减少首屏开销

页面下方会生成类似这样的代码:

html
<script src="https://giscus.app/client.js"
        data-repo="yourname/blog-comments"
        data-repo-id="R_xxx"
        data-category="Comments"
        data-category-id="DIC_xxx"
        data-mapping="pathname"
        data-strict="0"
        data-reactions-enabled="1"
        data-emit-metadata="0"
        data-input-position="top"
        data-theme="preferred_color_scheme"
        data-loading="lazy"
        data-lang="zh-CN"
        crossorigin="anonymous"
        async>
</script>

data-repo-id 和 data-category-id 一定要填,否则部分场景下会加载失败。

第四步:在 Next.js 里接入

不建议直接往页面塞 <script>,Next.js 里用 next/script 更可控,还能配合骨架屏避免布局跳动。

tsx
"use client";

import Script from "next/script";
import { useEffect, useRef, useState } from "react";

export default function CommentSection() {
  const boxRef = useRef<HTMLDivElement>(null);
  const [ready, setReady] = useState(false);

  useEffect(() => {
    const box = boxRef.current;
    if (!box) return;

    // 监听 giscus 注入的 iframe,加载完成后隐藏骨架
    const observer = new MutationObserver((mutations) => {
      for (const m of mutations) {
        for (const node of m.addedNodes) {
          if (
            node instanceof HTMLIFrameElement &&
            node.classList.contains("giscus-frame")
          ) {
            node.addEventListener("load", () => setReady(true), { once: true });
          }
        }
      }
    });
    observer.observe(box, { childList: true, subtree: true });
    return () => observer.disconnect();
  }, []);

  return (
    <div className="mt-16 pt-8 border-t">
      <h2>评论</h2>
      <div className="giscus" ref={boxRef} />
      {!ready && (
        <div className="animate-pulse h-24 rounded-xl border" aria-hidden />
      )}
      <Script
        src="https://giscus.app/client.js"
        strategy="afterInteractive"
        data-repo="yourname/blog-comments"
        data-repo-id="R_xxx"
        data-category="Comments"
        data-category-id="DIC_xxx"
        data-mapping="pathname"
        data-strict="0"
        data-reactions-enabled="1"
        data-emit-metadata="0"
        data-input-position="top"
        data-theme="preferred_color_scheme"
        data-lang="zh-CN"
        data-loading="lazy"
        crossOrigin="anonymous"
      />
    </div>
  );
}

然后在文章页底部引入这个组件即可。

第五步:自定义域名加速

giscus.app 在国内访问可能不稳定。giscus 支持自建客户端域名:在 next.config 里配一条 rewrite 或反代,把 /giscus 指到 https://giscus.app,再把 src 换成自己的域名。

本站的做法是单独用一个子域名反代,前端直接引用该域名:

tsx
<Script src="https://giscus.example.com/client.js" ... />

注意反代时要保留完整的查询参数,否则主题和配置会丢。

主题跟随深浅色

data-theme="preferred_color_scheme" 会跟随系统主题,但站点手动切换主题时它不会变。需要监听自己的主题变化,向 iframe 发消息:

ts
const iframe = document.querySelector<HTMLIFrameElement>(".giscus-frame");
iframe?.contentWindow?.postMessage(
  { giscus: { setConfig: { theme: isDark ? "dark" : "light" } } },
  "https://giscus.app"
);

常见问题

评论区一直显示空白怎么办?

先看仓库是不是 public,再确认 giscus App 是否授权到了这个仓库。两个条件缺一个,iframe 都不会有内容。

换了域名后旧评论不见了?

因为 mapping 用的是 pathname,域名变了路径没变理论上还能对上。如果换过文章路径,需要到对应 Discussion 里手动改标题里的路径。

能不能不显示 reaction?

把 data-reactions-enabled 设为 0 即可,评论功能不受影响。

评论会被搜索引擎收录吗?

giscus 内容在 iframe 里,正文页面不会被索引,也不会影响页面 SEO。

能不能限制只有 GitHub 账号能评论?

这是 giscus 的默认行为,只能 GitHub 登录,无法匿名评论。想要匿名评论只能换 Waline 这类方案。

相关阅读

评论