Next.js 博客接入 giscus 评论完整教程
静态博客最麻烦的一块就是评论:没有后端、没有数据库,传统的评论系统要么收费,要么需要自建服务。giscus 用 GitHub Discussions 存评论,纯前端接入,免费且没有广告,是目前个人博客最省心的方案之一。
这篇文章记录本站接入 giscus 的完整过程,照着做大概十几分钟能跑起来。
为什么选 giscus
对比几个常见方案:
| 方案 | 成本 | 数据存放 | 是否需要后端 |
|---|---|---|---|
| giscus | 免费 | 自己的 GitHub 仓库 | 不需要 |
| Disqus | 免费但带广告 | 第三方 | 不需要 |
| Valine / Waline | 需自建或付费托管 | 自己的数据库 | 需要 |
| 自研评论 | 免费 | 自己的数据库 | 需要 |
如果你的博客源码本来就在 GitHub,giscus 几乎没有迁移成本,评论和代码在同一个账号体系下管理。
第一步:创建评论仓库
新建一个公开仓库专门存评论,不要和博客源码混在一起:
- 在 GitHub 新建仓库,例如
yourname/blog-comments - 必须是 public,私有仓库 giscus 读不到
- 进入仓库
Settings,勾选Discussions功能
仓库本身可以先留空,giscus 会在第一次有人评论时自动创建对应的 Discussion。
第二步:安装 giscus App
打开 GitHub Apps - giscus,点击 Install,选择刚创建的评论仓库授权。如果只授权单个仓库,记得在安装页里选中它。
第三步:生成配置
打开 giscus.app,输入仓库名,它会实时校验并给出 <script> 配置。几个关键选项:
- 映射关系(mapping):选
pathname,按页面路径匹配,同一篇文章不同域名也能对上 - Discussion 分类:选
General或Announcements,建议单独建一个Comments分类,只搜索该分类 - 输入框位置:放评论上方还是下方,看个人习惯
- 懒加载:建议开启,减少首屏开销
页面下方会生成类似这样的代码:
<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 更可控,还能配合骨架屏避免布局跳动。
"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 换成自己的域名。
本站的做法是单独用一个子域名反代,前端直接引用该域名:
<Script src="https://giscus.example.com/client.js" ... />
注意反代时要保留完整的查询参数,否则主题和配置会丢。
主题跟随深浅色
data-theme="preferred_color_scheme" 会跟随系统主题,但站点手动切换主题时它不会变。需要监听自己的主题变化,向 iframe 发消息:
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 这类方案。
相关阅读
- 如何给自己的网站接入 CMS:让写文章不用手敲 Markdown
- 用 Next.js 搭建个人博客并部署到 Cloudflare:从零开始搭一个同类站点