Skip to content

VitePress 集成 Giscus 评论:私有源码仓与公开 Pages 仓怎么选

仲灏2026-06-30约 1 分钟

<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 时踩了两个坑:

  1. 评论必须绑在公开仓库:源码仓若是 private,Discussions 外人不可见,评论区无法正常工作。
  2. 发布仓 ≠ 评论仓,但 Pages 公开仓可以当评论仓:静态 HTML 推到 example-user.github.io 这类公开仓时,Giscus 可以直接挂在这个仓的 Discussions 上。

本文记录从选型、GitHub 配置到 VitePress 主题接入的完整流程,代码结构可复用到任意 VitePress 2 + 自定义主题项目。

Giscus 是什么

Giscus 基于 GitHub Discussions,由 giscus GitHub App 读写讨论。相比 Gitalk:

对比项GiscusGitalk(Issues 方案)
数据模型DiscussionsIssues
维护状态活跃社区维护,集成略旧
登录GitHub OAuthGitHub OAuth
页面映射pathname / URL / title 等自定义 issue id

VitePress 生态常用 vitepress-plugin-comment-with-giscus,在客户端把评论组件挂到 .content-container 底部,无需手写 iframe。

先想清楚:评论挂在哪个 GitHub 仓库?

典型发布链路:

text
私有源码仓(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/giscusInstall,仅授权 Pages 公开仓(不要选私有源码仓)。

3. 在 giscus.app 生成参数

打开 giscus.app/zh-CN,按向导选择:

  • Repositoryexample-user/example-blog-pages
  • Page ↔ Discussion mappingpathname(与站点 permalink 一致时最省心)
  • Discussion categoryGeneral
  • Theme / Language:按站点主题与语言选择

页面底部会生成 <script>,记下两个 ID(公开信息,会出现在前端 embed 里):

html
data-repo-id="R_kgDOxxxx"
data-category-id="DIC_kwDOxxxx"

第二步:VitePress 项目配置

目录约定

text
docs/
  .vitepress/
    config.mts          # 站点主配置
    config/
      giscus.mts        # Giscus 专用配置(推荐拆文件)
    theme/
      index.ts          # 主题入口,注入 giscusConfig

config/giscus.mts

ts
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 注入环境变量

ts
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 / 本地构建:

bash
GISCUS_REPO_ID=R_kgDOxxxx GISCUS_CATEGORY_ID=DIC_kwDOxxxx pnpm run build

主题入口 theme/index.ts

自定义主题若封装了 createMaistackTheme,传入 giscus 即可;等价于在主题里调用插件:

ts
import { createMaistackTheme } from "vitepress-theme-maistack";
import { giscusConfig } from "../config/giscus.mts";

export default createMaistackTheme({
  siteData: siteDataJson,
  giscus: giscusConfig,
});

主题内部逻辑(简化):

ts
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 要求 reporepoIdcategoryId 均非空;任一缺失则 不会挂载 评论区。

安装依赖

在主题包或站点根目录:

bash
pnpm add vitepress-plugin-comment-with-giscus @giscus/vue

第三步:与 Gitalk 迁移

若 Layout 里仍有 Gitalk 组件,启用 Giscus 后应 移除 Gitalk,否则正文底部会出现两套评论。

Giscus 由插件插入 .content-container 末尾;Gitalk 若在 #doc-after 槽位渲染,两者会并存。

单页开关

全局默认开启时,某页关闭评论:

yaml
---
comment: false
---

首页默认不显示可在配置里设 homePageShowComment: false

验证清单

  1. 重启 pnpm devdefine 与环境变量变更需重启)。
  2. 打开任意文章页,DevTools 中应存在 id="giscus" 节点。
  3. giscus-widgetrepo 属性应为 公开 Pages 仓,不是私有源码仓。
  4. 用 GitHub 账号登录后可发帖;讨论出现在该仓 Discussions 列表。
  5. 生产构建后部署到 Pages,线上再测一次(避免只在 dev 有效)。

常见问题

评论区完全空白

  • repoId / categoryId 为空或未重启 dev。
  • 绑错了 私有仓库
  • 未安装 Giscus App 或未授权目标仓。

分类对不上

category: "General" 必须与 GitHub Discussions 分类名 完全一致(大小写、空格)。

站点 permalink 若为 /pages/20260630120000/,Discussion 会按路径 /pages/20260630120000/ 关联;改 permalink 会导致旧讨论「对不上新 URL」,迁移 permalink 前要有心理预期。

深色模式主题不同步

插件会监听 html.dark 切换 lightTheme / darkTheme;若用 preferred_color_scheme,深浅色可共用同一 theme 名。

小结

  1. 私有源码 + 公开 Pages 时,Giscus 绑 公开 Pages 仓,不要绑私有源码仓。
  2. 在 GitHub 开 Discussions,安装 giscus app,在 giscus.apprepoId / categoryId
  3. VitePress 侧用 vitepress-plugin-comment-with-giscus + 主题 setup() 挂载;构建时用环境变量注入 ID。
  4. 从 Gitalk 迁移时记得 删掉旧评论组件,并用 frontmatter 控制单页开关。

按以上步骤,访客在 blog.example.com 留言,数据落在公开 Pages 仓的 Discussions,与私有 Markdown 源码解耦,又满足静态站「无后端」的评论需求。

本文为个人静态站实践脱敏整理,仓库名、域名、ID 均为示例,请替换为自己的 GitHub 仓库与 giscus.app 生成值。

延伸阅读