博客上线之后,总得有个评论功能吧?
自建评论系统是个坑——存评论要数据库,审核要后台,防垃圾要验证码,还得处理通知。我一个人维护博客,不想在这些事上花时间。
朋友推荐了 Giscus,一看,基于 GitHub Discussions 的评论系统。评论直接存你仓库的 Discussions 里,GitHub 帮你处理一切。没后端、没数据库、没审核面板,甚至不用注册——评论者用 GitHub 账号就行。
我花了半小时接好,踩了两个坑,这里记录一下。
实操步骤
1. 启用 GitHub Discussions
打开你的博客仓库页面,点顶部的 Settings 标签页(不是项目设置,是仓库设置)。
往下翻到 Features 区块,找到 Discussions,勾上。
勾上之后页面顶部会多一个 Discussions 标签。点进去,如果还没创建过分类,GitHub 会提示你创建一个。选默认的 Announcements 就行,后面可以在 giscus 配置里指定用哪个分类——我推荐新建一个专门的分类,比如叫 Blog Comments,方便和项目公告区分。
创建新分类:Discussions 页面 → 左侧 "Categories" → 点 New category。分类名填
Blog Comments,格式选 Discussion,其他默认。
2. 配置 giscus
打开 giscus.app/zh-CN,页面上是一个表单,从上到下一项一项填:
仓库:填 你的 GitHub 用户名/仓库名,比如 siwei-dev/siwei-blog。输入框会帮你搜索,搜到自己的仓库后点选即可。这一步完成后页面会自动提取下面两个只读字段:
- data-repo-id:giscus 自动从 GitHub API 获取你的仓库 ID
- data-category:从你的仓库 Discussions 里读取分类列表,下拉选择你刚创建的
Blog Comments - data-category-id:选中分类后自动填充
页面 ↔ 讨论映射:选 "包含页面标题的路径名"。这样每篇文章的 slug 自动映射到一个独立的 Discussion,不会串。
分类:选 Announcements(就是你刚创建的 Blog Comments,giscus 里显示的可能是你仓库里已有的分类名)。
特性:按需勾选。建议勾上"评论框在上方"(评论框放在已有评论上面,不用滚到底才能评论)、"懒加载"(评论区域滚到视口内才开始加载,省带宽)。
主题:选你站点当前主题或日夜间自动切换。giscus 支持 "Preferred color scheme" 方式跟随系统。
填完后页面底部会出现一段 <script> 标签,里面包含了 data-repo、data-repo-id、data-category、data-category-id、data-mapping、data-theme 等属性。记下这四个 id 值,后面要用:data-repo-id、data-category-id。
3. 代码接入
如果你的博客是 Nuxt 3 项目(我的是),创建一个 Vue 组件来加载 giscus:
<!-- components/GiscusComment.vue -->
<template>
<div class="giscus" ref="giscusContainer" />
</template>
<script setup>
const colorScheme = useColorMode()
const loadGiscus = () => {
const container = document.getElementById('giscus-container')
if (!container || container.querySelector('iframe')) return
const script = document.createElement('script')
script.src = 'https://giscus.app/client.js'
script.setAttribute('data-repo', '你的仓库名')
script.setAttribute('data-repo-id', '你记下的 repo-id')
script.setAttribute('data-category', 'Blog Comments')
script.setAttribute('data-category-id', '你记下的 category-id')
script.setAttribute('data-mapping', 'pathname')
script.setAttribute('data-strict', '0')
script.setAttribute('data-reactions-enabled', '1')
script.setAttribute('data-emit-metadata', '0')
script.setAttribute('data-input-position', 'top')
script.setAttribute('data-theme', colorScheme.value === 'dark' ? 'dark' : 'light')
script.setAttribute('data-lang', 'zh-CN')
script.setAttribute('crossorigin', 'anonymous')
script.setAttribute('data-loading', 'lazy')
container.appendChild(script)
}
onMounted(() => {
loadGiscus()
})
watch(colorScheme, () => {
// 主题切换时重新加载
const container = document.getElementById('giscus-container')
if (container) {
container.querySelector('iframe')?.remove()
container.querySelector('script')?.remove()
loadGiscus()
}
})
</script>
在文章详情页引入这个组件:
<!-- pages/posts/[slug].vue -->
<template>
<article>
<!-- 文章内容 -->
</article>
<div id="giscus-container" class="mt-12" />
<ClientOnly>
<GiscusComment />
</ClientOnly>
</template>
关键点:
- 用
ClientOnly包裹,giscus 脚本依赖浏览器 API,SSR 阶段不能执行。 - 监听主题切换事件,切换后重建 giscus iframe,否则深色模式不会自动跟随。
data-mapping="pathname"确保每个页面路径对应独立的 Discussion。
如果你的博客是纯静态 HTML,直接把 giscus.app 生成的 <script> 标签贴在 </body> 前就行,连组件都不用写。
踩了两个坑
第一个坑:CSP 拦截
配置好刷新页面,评论区域一片空白。打开控制台:
Loading the script violates the following Content Security Policy directive:
"script-src 'self' 'unsafe-inline'"
我的前端项目配了 CSP,只允许加载本站脚本,giscus.app 的脚本被浏览器拦了。
在 CSP 里加几行白名单:
script-src 'self' 'unsafe-inline' https://giscus.app
style-src 'self' 'unsafe-inline' https://giscus.app
frame-src https://giscus.app
connect-src 'self' https://giscus.app https://api.github.com
没配 CSP 的项目可以跳过这里。
第二个坑:本地代理和 Chrome 安全策略打架
CSP 修好之后还是空白,控制台冒出另一个错:
Access to fetch at '' from origin '' has been blocked by CORS policy:
Permission was denied for this request to access the loopback address space.
我平时用 Steam++(Watt Toolkit)加速 GitHub 访问。它开了 Hosts 加速模式,把 api.github.com 解析到了 127.0.0.1,通过本地代理转发。Chrome 的 Private Network Access 安全策略拦了这种"公网页面 → 本地回路地址"的请求。
切换到系统代理模式就好——Steam++ 里"平台加速 → 右上角加速模式 → 系统代理"。重启完问题消失。
这个坑只在本地开发有。部署到服务器之后
api.github.com正常解析到公网 IP,不会触发这个限制。
两个坑都不难解决,但排查过程花了我不少时间。第一个是 CSP 策略拦了第三方脚本,第二个是代理工具改了 DNS 解析导致 Chrome 安全策略误判。两个都是安全机制在正常工作,只是碰在一起就出问题了。
Giscus 接好之后就没再管过——评论正常显示,深色模式自动跟随,表情反应也有。免费的,零维护,数据还在自己仓库里。对于个人博客来说,这就是我要的方案。
