- 后端
【免费下载链接】giscus
A commenting system powered by GitHub Discussions. :octocat: :speech_balloon: :gem:
giscus 是一个完全依托 GitHub Discussions 构建的开源评论系统,让网站访客通过 GitHub 账号即可发表评论与表情回应。本文以仓库中的 README.pl.md(项目主 README 的波兰语译本,内容与 README.md 一致)为主体,结合仓库源码深入解析其工作原理、核心特性、配置方式与迁移方案。读完本文,你将理解 giscus 如何用 GitHub Discussions 替代自建数据库与后端评论服务,并掌握giscus.json、data-属性等进阶配置的实战用法。
项目概览:giscus 是什么
giscus 是一个由 GitHub Discussions 驱动的评论系统(A comments system powered by GitHub Discussions)。访客可以在你的网站上通过 GitHub 发表评论和表情回应,而所有的评论数据都存放在 GitHub 的 Discussion 中,无需自建任何数据库。该项目深受 utterances 启发,但与 utterances 基于 GitHub Issues 不同,giscus 基于 GitHub Discussions。
从 README 中可以直接概括出它的核心卖点:
- 开源:项目以开放源代码的形式发布,任何开发者都可以查看、部署和二次开发。
- 无追踪、无广告、永久免费:不采集访客数据,不插入广告。
- 无需数据库:所有数据全部存储在 GitHub Discussions 中,评论即"Issue/讨论"数据。
- 支持自定义主题:不仅内置多套主题,还允许通过 CSS 文件自定义外观。
- 支持多语言:内置数十种语言的界面翻译。
- 高度可配置:通过仓库根目录的
giscus.json和<script>标签的data-属性进行深度定制。 - 自动同步:自动从 GitHub 拉取新的评论与编辑内容。
- 可自托管:可以部署在自己的服务器上(详见仓库中的 SELF-HOSTING.md)。
README 中特别强调了一个重要前提:giscus 仍处于积极开发阶段,GitHub 也在持续演进 Discussions 及其 API,因此部分功能可能随时间变化或出现不兼容。这意味着使用时建议关注项目更新与 GitHub API 变更。
工作原理:从页面映射到 Discussion 的完整链路
README 的 "How it works" 章节给出了最核心的机制描述,其完整链路可以拆解为以下几步:
1. 搜索并映射 Discussion
当 giscus 在页面中加载时,它会调用GitHub Discussions 搜索 API,根据你所选择的映射方式(Mapping)来查找与当前页面关联的 Discussion。可选的映射包括:
- 页面的完整 URL(
URL) - 页面的
pathname(路径名) - 页面的
<title>(标题)等
这一逻辑在仓库中由 pages/api/discussions/index.ts 的get分支实现:服务端把repo、term、category、strict、number等查询参数组装成 GraphQL 查询,调用 GitHub 的 search API;如果命中讨论(discussionCount > 0),则取第一个节点作为当前页面对应的讨论(pages/api/discussions/index.ts),否则返回 404 "Discussion not found"。
2. 自动创建 Discussion
如果找不到匹配的 Discussion,giscus bot 会在访客第一次发表评论或表情回应时自动创建一条 Discussion。前端组件 components/Widget.tsx 中的handleDiscussionCreateRequest会构造讨论正文:
body: `# ${term}\n\n${description || ''}\n\n${cleanAnchor(backLink || origin)}`即"标题 + 页面描述 + 页面链接"三段式正文,随后通过POST /api/discussions调用 GitHub 的createDiscussion变更接口完成创建。值得一提的是,该接口在创建时会自动在正文末尾追加 SHA-1 哈希注释(见下文"严格匹配"部分),pages/api/discussions/index.ts 中对应实现为:
const hashTag = `<!-- sha1: ${await digestMessage(params.input.title)} -->`; params.input.body = `${params.input.body}\n\n${hashTag}`;3. 访客授权(OAuth 流程)
要发表评论,访客必须授权 giscus app 代表自己发帖,授权走的是标准的 GitHub OAuth 流程。仓库中对应模块为:
- pages/api/oauth/authorize.ts 与 pages/api/oauth/authorized.ts:发起与完成授权;
- pages/api/oauth/token.ts:换取访问令牌;
- lib/oauth/state.ts 与 lib/oauth/encryption.ts:负责会话状态(session)的加解密,防止状态被篡改。
4. 评论与审核
除了通过 OAuth 在网站上评论,访客也可以直接到 GitHub Discussion 页面上发表评论。站长可以直接在 GitHub 上对评论进行审核(moderate)、编辑或删除——因为评论数据本质上就是 GitHub 上的讨论内容,GitHub 原生提供了一整套内容审核工具。
从实现上看,lib/adapter.ts 中的adaptDiscussion/adaptComment/adaptReply会把 GitHub GraphQL 返回的原始数据结构(评论、回复、表情分组、分页信息等)适配为前端组件所需的内部类型,并在渲染前通过processCommentBody对评论 HTML 做安全化处理(如给链接加上rel="noopener noreferrer nofollow"、注入代码块复制按钮等,见 lib/adapter.ts)。
数据与同步:为什么"无需数据库"
giscus 无需数据库,原因在于所有评论数据都存储在 GitHub Discussions 中,GitHub 的 GraphQL API 就是它的"数据库"。
前端通过 services/giscus/discussions.ts 中的useDiscussion(基于 SWR 的无限分页 Hook)按页拉取/api/discussions数据,并利用 SWR 的重验证机制自动获取来自 GitHub 的新评论与编辑——这正是 README 中"Automatically fetches new comments and edits from GitHub"承诺的实现基础(services/giscus/discussions.ts 中配置了revalidateOnFocus、revalidateOnReconnect等策略,且对 403/404/429 状态跳过重试)。仓库还提供了 pages/api/webhook.ts 作为 GitHub Webhook 入口,用于讨论变更的事件驱动同步。
多语言支持
README 宣称 giscus 支持多种语言("Supports multiple languages")。仓库中的实现证据非常直观:
- locales/ 目录下为每种语言提供了
common.json与config.json两个翻译文件,目前覆盖阿拉伯语、白俄罗斯语、保加利亚语、中文(简/繁/港)等数十种语言; - lib/i18n.tsx 中的
availableLanguages常量定义了全部受支持语言的代码与名称; - i18n.fallbacks.json 提供语言回退映射,当某语言缺少某个翻译键时回退到其基础语言。
界面文案通过 next-translate 的useGiscusTranslation/Trans组件读取(lib/i18n.tsx),日期与相对时间则使用Intl.DateTimeFormat/Intl.RelativeTimeFormat按语言本地化展示(lib/i18n.tsx),并为阿拉伯语、波斯语、希伯来语设置了 RTL 方向。
如果你希望为 giscus 增加新的语言翻译,可参考仓库中的 CONTRIBUTING.md 中关于本地化贡献的说明。
主题定制
"支持自定义主题"是 README 的核心卖点之一。仓库内置主题位于 styles/themes/,包括:
- GitHub 风格系列:
light、dark、light_high_contrast、dark_high_contrast、dark_dimmed以及色觉障碍友好主题light_protanopia、light_tritanopia、dark_protanopia、dark_tritanopia; - 极简风格:
noborder_light、noborder_dark、noborder_gray、transparent_dark; - 第三方风格:
cobalt、purple_dark、gruvbox(含gruvbox_dark/gruvbox_light)、catppuccin(latte/frappe/macchiato/mocha)、fro; preferred_color_scheme:跟随访问者系统配色偏好自动切换。
lib/variables.ts 中的availableThemes常量完整罗列了这些主题名,此外还允许通过data-theme传入/path/to/theme.css或https://...形式的自定义 CSS 地址(Theme类型定义见 lib/variables.ts),styles/themes/custom_example.css 提供了自定义主题的参考模板。
高度可配置:仓库级配置giscus.json
README 将"Extensively configurable"列为重要特性,并在 "Advanced usage" 章节指出:可以通过在仓库根目录创建giscus.json来添加额外配置(例如限定允许加载 giscus 的来源域名)。完整说明见 ADVANCED-USAGE.md,这里结合仓库中的真实配置与源码给出核心字段解读。
仓库自身的 giscus.json 内容如下:
{ "origins": [ "https://giscus.app", "https://giscus.vercel.app", "https://giscus-component.vercel.app" ], "originsRegex": [ "https://giscus-git-([A-z0-9]|-)*giscus\\.vercel\\.app", "https://giscus-component-git-([A-z0-9]|-)*giscus\\.vercel\\.app", "http://selfhost:[0-9]+" ], "defaultCommentOrder": "oldest" }origins:限定可加载来源
origins接受一个字符串数组,giscus 会拿加载页面自身的window.origin与这些字符串逐一比较(等价于string === window.origin)。若你的仓库不希望被任意站点嵌入使用,就在giscus.json中列出允许的域名白名单。仓库中assertOrigin的实现位于 lib/config.ts,在 pages/widget.tsx 中被用于设置 CSP 头:来源合法时设置frame-ancestors 'self' <origins>,非法来源则直接设置frame-ancestors 'none'并重定向,从服务端层面拒绝被嵌入。
originsRegex:正则匹配来源
与origins类似,但接受正则表达式模式数组,使用new RegExp(pattern).test(window.origin)判断来源,适合覆盖动态子域名(例如仓库配置中用于匹配 Vercel 预览分支域名的规则)。origins与originsRegex可以组合使用;若两者都为空(或未定义),giscus 将默认放行所有来源。
defaultCommentOrder:默认评论排序
设置评论的默认排序方式,取值"oldest"(从旧到新)或"newest"(从新到旧),默认值为"oldest"。该值在 pages/widget.tsx 中被读取为repoConfig.defaultCommentOrder || 'oldest',前端 services/giscus/discussions.ts 中的useFrontBackDiscussion会根据orderBy决定前后两段评论的拼接顺序(services/giscus/discussions.ts)。类型定义CommentOrder = 'oldest' | 'newest'见 lib/types/giscus.ts。
更多data-属性与<meta>标签
除了giscus.json,README 提到的"高度可配置"还体现在<script>标签的data-属性上(详见 ADVANCED-USAGE.md):
data-strict="1":GitHub 搜索讨论时使用模糊匹配,当存在标题相似的多个讨论时可能返回错误结果。开启严格匹配后,giscus 不再用讨论标题作为搜索词,而是计算讨论标题的 SHA-1 哈希并在讨论正文中搜索该哈希。giscus 自动创建的讨论都会在正文中写入形如<!-- sha1: cad60a29d1b50cbeb42ec2ff630fc508afb1d2e3 -->的 HTML 注释(GitHub 页面上不可见);如果你在启用该选项之前已有存量讨论,需要手动编辑讨论、把标题的 SHA-1 哈希加到正文任意位置。仓库中POST /api/discussions正是这样生成哈希注释的(pages/api/discussions/index.ts)。data-theme:除内置主题外,可传入一个 CSS 文件 URL,giscus 会把它构建为<link rel="stylesheet">元素追加到<head>末尾。需要注意:加载外部 CSS 可能存在安全风险,请确保你信任该 CSS 的作者与提供方,并让站内用户知晓这一风险。giscus:backlink<meta>标签:如果页面带有<meta name="giscus:backlink" content="...">,giscus 在创建新讨论时会用其content作为回链地址,而不是默认的window.location.href。这在希望使用短链接、或担心改版后 URL 失效的场景下非常有用。该逻辑对应前端创建讨论时传入的backLink(components/Widget.tsx)。
与 React / Vue / Svelte 集成
对于使用前端框架的开发者,README 提示:要在 React、Vue 或 Svelte 项目中使用 giscus,可以选用giscus 组件库(giscus component library)。此外,仓库还支持通过postMessage与 giscus 的<iframe>进行双向通信:
- giscus → 父页面:错误信息(
IErrorMessage)、讨论元数据(IMetadataMessage,需开启data-emit-metadata="1"后周期性地发出,且仅在讨论存在时发出); - 父页面 → giscus:
ISetConfigMessage,可在不重新加载<script>/<iframe>的情况下动态更新主题、仓库、分类、映射词、评论排序、语言等配置(所有属性均为可选,可只更新子集)。
这些消息的 TypeScript 接口定义集中在 lib/types/giscus.ts(如ISetConfigMessage见 lib/types/giscus.ts),前端 pages/widget.tsx 中也实现了对setConfig消息的监听处理,可据此验证消息协议的具体字段。
自托管(Self-hosting)
README 强调 giscus可以自托管。仓库根目录的 SELF-HOSTING.md 是完整的自托管指南,需要配置的环境变量集中在 lib/variables.ts,主要包括:GitHub App 相关的GITHUB_APP_ID、GITHUB_CLIENT_ID、GITHUB_CLIENT_SECRET、GITHUB_INSTALLATION_ID、GITHUB_PRIVATE_KEY、GITHUB_TOKEN,以及会话加密密钥ENCRYPTION_PASSWORD、对外服务地址NEXT_PUBLIC_GISCUS_APP_HOST、来源白名单ORIGINS/ORIGINS_REGEX等。具体部署步骤(如 Vercel 或自建服务器)请以该文档为准。
迁移指南:从 Issues 方案平滑切换
README 的 "Migrating" 章节为存量用户提供了迁移路径:如果你此前使用的是基于 GitHub Issues 的评论系统(如utterances、gitalk),可以把现有的 Issues 转换为 Discussions(在 GitHub 讨论管理功能中执行转换)。转换完成后,只需确认讨论标题与页面之间的映射关系正确,giscus 就会自动复用这些讨论,无需重新造数据。
迁移完成后,建议核对:
- 每个页面的映射方式(URL / pathname / title)与对应讨论标题一致;
- 如果启用了
data-strict="1",存量讨论正文中需包含标题的 SHA-1 哈希(参见上文); - 评论顺序与审核权限符合预期,因为评论数据现在属于 GitHub Discussions 的管辖范围。
参与贡献与其他说明
如果你希望参与 giscus 的开发、翻译或主题创作,请查阅 CONTRIBUTING.md。README 中还列出了若干公开使用 giscus 的站点(如 laymonage.com、os.phil-opp.com、Stats and R 播客等),并在 GitHub 上设有giscus话题供社区发现更多使用者。
最后再次提醒:README 明确指出 giscus 与 GitHub Discussions 本身都处于活跃演进阶段,功能可能变动;在使用本指南中的配置项时,建议以当前仓库的实际实现与 GitHub 最新 API 文档为准。
- 后端
【免费下载链接】giscus
A commenting system powered by GitHub Discussions. :octocat: :speech_balloon: :gem:
相关推荐
giscus 评论系统指南:基于 GitHub Discussions 的开源评论组件集成与高级配置
giscus 评论系统指南:基于 GitHub Discussions 的开源评论组件集成与高级配置 导读 giscus 是一个由 GitHub Discuss
后端gs-quant 时间序列经济计量:用 prices 函数从收益率序列重建价格水平
gs quant 时间序列经济计量:用 prices 函数从收益率序列重建价格水平 在量化研究中,价格与收益率之间的互相转换是最基础也最高频的操作。gs qua
后端giscus 技术全解:基于 GitHub Discussions 的开源评论系统原理、配置与迁移实战
giscus 技术全解:基于 GitHub Discussions 的开源评论系统原理、配置与迁移实战 导读 本文以 giscus 项目官方德语 README(
后端
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考