Mobile wallpaper 1
1023 字
5 分钟
Mizuki实现Giscus评论区
2025-09-13
2025-12-05
统计加载中...

准备工作#

  1. 创建 GitHub 仓库
    • 新建一个 公开(public 的 GitHub 仓库。
    • 在仓库设置中 启用 Discussions 功能
  2. 生成 Giscus 配置代码
    • 访问 giscus官网,根据你的需求完成配置。
    • 配置完成后,复制生成的 <script> 代码块,例如:
<script src="https://giscus.app/client.js"
data-repo="Leaf-0w0/blog-giscus"
data-repo-id="***"
data-category="Announcements"
data-category-id="***"
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"
async>
</script>

配置 Mizuki 主题#

1. 修改评论配置文件#

打开 src/config.ts,将原有的 Twikoo 配置替换为 Giscus 配置:
原内容:

export const commentConfig: CommentConfig = {
enable: false, // 启用评论功能。当设置为 false 时,评论组件将不会显示在文章区域。
twikoo: {
envId: "https://twikoo.vercel.app",
lang: "en", // 设置 Twikoo 评论系统语言为英文
},
};

修改为:

export const commentConfig: CommentConfig = {
enable: true, // 启用评论功能。当设置为 false 时,评论组件将不会显示在文章区域。
giscus: {
enable: true,
repo: "Leaf-0w0/blog-giscus",
repoId: "***",
category: "Announcements",
categoryId: "***",
mapping: "pathname",
strict: "0",
reactionsEnabled: "1",
emitMetadata: "0",
inputPosition: "top",
theme: "preferred_color_scheme",
lang: "zh-CN",
},
};

2. 添加 Giscus 组件#

src/components/comment/ 目录下创建新文件 Giscus.astro,并粘贴以下代码(可删除原有的 Twikoo.astro 文件):

---
import { commentConfig } from "@/config";
interface Props {
path: string;
}
const giscusConfig = commentConfig.giscus;
---
<div class="giscus-container"></div>
<script is:inline define:vars={{ giscusConfig }}>
(function () {
// 配置项
const CONFIG = {
...giscusConfig,
mapping: giscusConfig.mapping || 'pathname',
strict: giscusConfig.strict || '0',
reactionsEnabled: giscusConfig.reactionsEnabled || '1',
emitMetadata: giscusConfig.emitMetadata || '0',
inputPosition: giscusConfig.inputPosition || 'top',
lang: giscusConfig.lang || 'zh-CN',
loading: 'lazy'
};
// 获取当前主题
function getTheme() {
return document.documentElement.classList.contains('dark') ? 'dark' : 'light';
}
// 向 Giscus iframe 发送消息更新配置
function updateGiscusTheme() {
const iframe = document.querySelector('iframe.giscus-frame');
if (!iframe || !iframe.contentWindow) return;
const theme = getTheme();
iframe.contentWindow.postMessage(
{ giscus: { setConfig: { theme: theme } } },
'https://giscus.app'
);
}
// 注入 Giscus 脚本
function loadGiscus() {
const root = document.querySelector('.giscus-container');
// 如果容器不存在,或者已经有 iframe 了,则不处理
if (!root || root.querySelector('iframe.giscus-frame')) return;
// 如果已有旧的 script 标签(Swup 切换可能导致残留),先清理
const oldScript = document.getElementById('giscus-script');
if (oldScript) oldScript.remove();
const theme = getTheme();
const script = document.createElement('script');
script.id = 'giscus-script';
script.src = 'https://giscus.app/client.js';
script.async = true;
// 设置核心参数
script.setAttribute('data-repo', CONFIG.repo);
script.setAttribute('data-repo-id', CONFIG.repoId);
script.setAttribute('data-category', CONFIG.category);
script.setAttribute('data-category-id', CONFIG.categoryId);
script.setAttribute('data-mapping', CONFIG.mapping);
script.setAttribute('data-strict', CONFIG.strict);
script.setAttribute('data-reactions-enabled', CONFIG.reactionsEnabled);
script.setAttribute('data-emit-metadata', CONFIG.emitMetadata);
script.setAttribute('data-input-position', CONFIG.inputPosition);
script.setAttribute('data-lang', CONFIG.lang);
script.setAttribute('data-loading', CONFIG.loading);
// 关键:直接设置当前主题,无需加载后回调
script.setAttribute('data-theme', theme);
root.appendChild(script);
}
// 监听 html class 变化(主题切换)
// 只有当 observer 不存在时才创建,防止多重绑定
if (!window._giscusObserver) {
const observer = new MutationObserver((mutations) => {
mutations.forEach((mutation) => {
if (mutation.type === 'attributes' && mutation.attributeName === 'class') {
updateGiscusTheme();
}
});
});
observer.observe(document.documentElement, { attributes: true });
window._giscusObserver = observer;
}
// 初始化逻辑
function init() {
loadGiscus();
}
// 立即执行一次
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', init);
} else {
init();
}
// Swup 适配逻辑
// 使用一个标志位或检查是否已绑定,避免 script 重新执行导致的多重绑定
if (window.swup && !window._giscusSwupListenerAdded) {
const handleSwup = () => {
// Swup 替换内容后,DOM 里的 iframe 会消失,需要重新 load
init();
};
window.swup.hooks.on('content:replace', handleSwup);
window.swup.hooks.on('page:view', handleSwup);
window._giscusSwupListenerAdded = true;
} else if (!window.swup && typeof document !== 'undefined') {
// 针对 Swup 还没加载完成的边缘情况
document.addEventListener('swup:enable', () => {
if (window.swup && !window._giscusSwupListenerAdded) {
window.swup.hooks.on('content:replace', init);
window.swup.hooks.on('page:view', init);
window._giscusSwupListenerAdded = true;
}
}, { once: true }); // 仅执行一次
}
})();
</script>
<style>
.giscus-container {
width: 100%;
margin-top: 1rem;
min-height: 200px; /* 防止加载时高度塌陷带来的布局抖动 */
transition: opacity 0.3s;
}
.giscus-container iframe.giscus-frame {
width: 100%;
border-radius: var(--radius-large, 8px); /* 提供 fallback */
border: 1px solid var(--line-divider, rgba(0,0,0,0.1));
background: transparent;
transition: border-color 0.15s;
}
.giscus-container:hover iframe.giscus-frame {
border-color: var(--primary, #3b82f6);
}
</style>

3. 更新评论组件入口#

编辑 src/components/comment/index.astro,替换 Twikoo 相关引用:
原内容:

import Twikoo from "./Twikoo.astro"; //文件内第4行
if (commentConfig?.enable && commentConfig?.twikoo) { //文件内第16行
commentService = "twikoo"; //文件内第17行
{commentService === 'twikoo' && <Twikoo path={path} />} //文件内第22行

修改为:

import Giscus from "./Giscus.astro";
if (commentConfig?.enable) {
if (commentConfig?.giscus) {
commentService = "giscus";
}
{commentService === 'giscus' && <Giscus path={path} />}

4. 更新类型定义#

src/types/config.ts 中,将 Twikoo 类型替换为 Giscus 类型:
原内容:

twikoo?: TwikooConfig; //文件内第134行
type TwikooConfig = { //文件内第137行
envId: string; //文件内第138行
region?: string; //文件内第139行

修改为:

giscus?: GiscusConfig;
type GiscusConfig = {
enable: boolean;
repo: string;
repoId: string;
category: string;
categoryId: string;
mapping?: string;
strict?: string;
reactionsEnabled?: string;
emitMetadata?: string;
inputPosition?: string;
theme?: string;

完成修改#

完成以上步骤后,你的Mizuki主题即可成功集成Giscus评论系统

Mizuki实现Giscus评论区
https://blog.yuk1.uk/posts/mizuki-giscus/
作者
SuzuhaYuki
发布于
2025-09-13
许可协议
CC BY-NC-SA 4.0

部分信息可能已经过时