<div style="display: none;" hidden="true" aria-hidden="true" data-nosnippet>Are you an LLM? You can read better optimized documentation at /pages/20260630120000.md for this page in Markdown format</div>
背景
个人知识库用 VitePress 构建,Markdown 在本地仓库维护,构建产物推送到 GitHub Pages 的公开仓库,自定义域名例如 https://blog.example.com 指向 Pages。
早期评论用 Gitalk(基于 GitHub Issues),迁移到 Giscus 时踩了两个坑:
- 评论必须绑在公开仓库:源码仓若是 private,Discussions 外人不可见,评论区无法正常工作。
- 发布仓 ≠ 评论仓,但 Pages 公开仓可以当评论仓:静态 HTML 推到
example-user.github.io这类公开仓时,Giscus 可以直接挂在这个仓的 Discussions 上。
本文记录从选型、GitHub 配置到 VitePress 主题接入的完整流程,代码结构可复用到任意 VitePress 2 + 自定义主题项目。
Giscus 是什么
Giscus 基于 GitHub Discussions,由 giscus GitHub App 读写讨论。相比 Gitalk:
| 对比项 | Giscus | Gitalk(Issues 方案) |
|---|---|---|
| 数据模型 | Discussions | Issues |
| 维护状态 | 活跃 | 社区维护,集成略旧 |
| 登录 | GitHub OAuth | GitHub OAuth |
| 页面映射 | pathname / URL / title 等 | 自定义 issue id |
VitePress 生态常用 vitepress-plugin-comment-with-giscus,在客户端把评论组件挂到 .content-container 底部,无需手写 iframe。
先想清楚:评论挂在哪个 GitHub 仓库?
典型发布链路:
私有源码仓(Markdown + VitePress 配置)
│ pnpm build
▼
公开 Pages 仓(纯静态 HTML,force push)
│ CNAME
▼
blog.example.com(访客访问)| 仓库类型 | 示例 | 能否挂 Giscus |
|---|---|---|
| 私有源码仓 | example-user/example-blog | 不能(Discussions 不对外) |
| 公开 Pages 仓 | example-user/example-blog-pages | 可以 |
| 专用公开评论仓 | example-user/example-blog-comments | 可以(与 Gitalk 时代类似) |
推荐:源码私有、Pages 公开时,直接把 Giscus 绑在 Pages 公开仓;mapping: pathname 按页面路径(如 /pages/20260630120000/)归档讨论,与 HTML 在哪个 commit 无关。
第一步:GitHub 侧配置
以公开 Pages 仓 example-user/example-blog-pages 为例。
1. 开启 Discussions
仓库 Settings → General → Features,勾选 Discussions,初始化后保留 General 分类(名称需与下文配置一致)。
2. 安装 Giscus App
打开 github.com/apps/giscus,Install,仅授权 Pages 公开仓(不要选私有源码仓)。
3. 在 giscus.app 生成参数
打开 giscus.app/zh-CN,按向导选择:
- Repository:
example-user/example-blog-pages - Page ↔ Discussion mapping:
pathname(与站点permalink一致时最省心) - Discussion category:
General - Theme / Language:按站点主题与语言选择
页面底部会生成 <script>,记下两个 ID(公开信息,会出现在前端 embed 里):
data-repo-id="R_kgDOxxxx"
data-category-id="DIC_kwDOxxxx"第二步:VitePress 项目配置
目录约定
docs/
.vitepress/
config.mts # 站点主配置
config/
giscus.mts # Giscus 专用配置(推荐拆文件)
theme/
index.ts # 主题入口,注入 giscusConfigconfig/giscus.mts
import type { MaistackGiscusOptions } from "vitepress-theme-maistack";
declare const __GISCUS_REPO_ID__: string;
declare const __GISCUS_CATEGORY_ID__: string;
export const giscusConfig: MaistackGiscusOptions = {
repo: "example-user/example-blog-pages",
repoId: __GISCUS_REPO_ID__ || "R_kgDOxxxx",
category: "General",
categoryId: __GISCUS_CATEGORY_ID__ || "DIC_kwDOxxxx",
mapping: "pathname",
inputPosition: "bottom",
lang: "zh-CN",
locales: {
"zh-Hans": "zh-CN",
"en-US": "en",
},
homePageShowComment: false,
lightTheme: "preferred_color_scheme",
darkTheme: "preferred_color_scheme",
};repoId / categoryId 建议通过构建时注入,本地默认可写 fallback,避免未配环境变量时评论区静默不加载。
config.mts 注入环境变量
vite: {
define: {
__GISCUS_REPO_ID__: JSON.stringify(
process.env.GISCUS_REPO_ID ?? "R_kgDOxxxx",
),
__GISCUS_CATEGORY_ID__: JSON.stringify(
process.env.GISCUS_CATEGORY_ID ?? "DIC_kwDOxxxx",
),
},
},CI / 本地构建:
GISCUS_REPO_ID=R_kgDOxxxx GISCUS_CATEGORY_ID=DIC_kwDOxxxx pnpm run build主题入口 theme/index.ts
自定义主题若封装了 createMaistackTheme,传入 giscus 即可;等价于在主题里调用插件:
import { createMaistackTheme } from "vitepress-theme-maistack";
import { giscusConfig } from "../config/giscus.mts";
export default createMaistackTheme({
siteData: siteDataJson,
giscus: giscusConfig,
});主题内部逻辑(简化):
import giscusTalk from "vitepress-plugin-comment-with-giscus";
const giscus = isGiscusConfigured(options.giscus) ? options.giscus : undefined;
return {
extends: DefaultTheme,
Layout,
...(giscus
? {
setup() {
const { frontmatter } = toRefs(useData());
const route = useRoute();
giscusTalk(giscus, { frontmatter, route }, true);
},
}
: {}),
};isGiscusConfigured 要求 repo、repoId、categoryId 均非空;任一缺失则 不会挂载 评论区。
安装依赖
在主题包或站点根目录:
pnpm add vitepress-plugin-comment-with-giscus @giscus/vue第三步:与 Gitalk 迁移
若 Layout 里仍有 Gitalk 组件,启用 Giscus 后应 移除 Gitalk,否则正文底部会出现两套评论。
Giscus 由插件插入 .content-container 末尾;Gitalk 若在 #doc-after 槽位渲染,两者会并存。
单页开关
全局默认开启时,某页关闭评论:
---
comment: false
---首页默认不显示可在配置里设 homePageShowComment: false。
验证清单
- 重启
pnpm dev(define与环境变量变更需重启)。 - 打开任意文章页,DevTools 中应存在
id="giscus"节点。 giscus-widget的repo属性应为 公开 Pages 仓,不是私有源码仓。- 用 GitHub 账号登录后可发帖;讨论出现在该仓 Discussions 列表。
- 生产构建后部署到 Pages,线上再测一次(避免只在 dev 有效)。
常见问题
评论区完全空白
repoId/categoryId为空或未重启 dev。- 绑错了 私有仓库。
- 未安装 Giscus App 或未授权目标仓。
分类对不上
category: "General" 必须与 GitHub Discussions 分类名 完全一致(大小写、空格)。
pathname 映射与 permalink
站点 permalink 若为 /pages/20260630120000/,Discussion 会按路径 /pages/20260630120000/ 关联;改 permalink 会导致旧讨论「对不上新 URL」,迁移 permalink 前要有心理预期。
深色模式主题不同步
插件会监听 html.dark 切换 lightTheme / darkTheme;若用 preferred_color_scheme,深浅色可共用同一 theme 名。
小结
- 私有源码 + 公开 Pages 时,Giscus 绑 公开 Pages 仓,不要绑私有源码仓。
- 在 GitHub 开 Discussions,安装 giscus app,在 giscus.app 拿
repoId/categoryId。 - VitePress 侧用
vitepress-plugin-comment-with-giscus+ 主题setup()挂载;构建时用环境变量注入 ID。 - 从 Gitalk 迁移时记得 删掉旧评论组件,并用 frontmatter 控制单页开关。
按以上步骤,访客在 blog.example.com 留言,数据落在公开 Pages 仓的 Discussions,与私有 Markdown 源码解耦,又满足静态站「无后端」的评论需求。
本文为个人静态站实践脱敏整理,仓库名、域名、ID 均为示例,请替换为自己的 GitHub 仓库与 giscus.app 生成值。
