在像 GitHub Pages 這樣的平台上託管輕量級靜態博客有很多優點,但也會減少一些互動性。幸運的是,Giscus 存在,並提供了一種在靜態網站上嵌入用戶評論的方法。
目錄
Giscus 的工作原理
Giscus 使用 GitHub API 來讀取和存儲 GitHub 用戶在與倉庫相關的 Discussions 中發表的評論。
將 Giscus 客戶端腳本包嵌入您的網站,並使用正確的倉庫 URL 進行配置,用戶即可查看和撰寫評論(當登錄到 GitHub 時)。
這種方法是無服務器的,因為評論存儲在 GitHub 上,並在客戶端動態加載,因此非常適合像 AstroPaper 這樣的靜態博客。
設置 Giscus
Giscus 可以在 giscus.app 上輕鬆設置,但我仍會簡要概述過程。
先決條件
要使 Giscus 正常工作,需要滿足以下條件:
- 倉庫是 公開的
- 安裝了 Giscus 應用
- 為倉庫啟用了 Discussions 功能
如果由於任何原因無法滿足這些條件,則無法集成 Giscus。
配置 Giscus
接下來,需要配置 Giscus。在大多數情況下,預選的默認設置是合適的,只有在有特定原因並且知道自己在做什麼時才應修改它們。不用太擔心做出錯誤的選擇;您可以隨時稍後調整配置。
然而,您需要:
- 選擇 UI 的正確語言
- 指定要連接的 GitHub 倉庫,通常是包含您在 GitHub Pages 上託管的靜態 AstroPaper 博客的倉庫
- 如果您想確保沒有人可以直接在 GitHub 上創建隨機評論,請在 GitHub 上創建並設置一個
Announcement類型的討論 - 定義配色方案
配置設置後,Giscus 會為您提供一個生成的 <script> 標籤,您將在下一步中需要它。
簡單的腳本標籤
您現在應該有一個看起來像這樣的腳本標籤:
<script
src="https://giscus.app/client.js"
data-repo="[ENTER REPO HERE]"
data-repo-id="[ENTER REPO ID HERE]"
data-category="[ENTER CATEGORY NAME HERE]"
data-category-id="[ENTER CATEGORY ID HERE]"
data-mapping="pathname"
data-strict="0"
data-reactions-enabled="1"
data-emit-metadata="0"
data-input-position="bottom"
data-theme="preferred_color_scheme"
data-lang="en"
crossorigin="anonymous"
async
></script>
只需將其添加到網站的源代碼中。如果您使用 AstroPaper 並希望在帖子上啟用評論,請導航到 src/layouts/PostDetails.astro,並將其粘貼到您希望評論出現的位置,可能在 Share this post on: 按鈕下方。
<ShareLinks />
</div>
+ <script src="https://giscus.app/client.js"
+ data-repo="[ENTER REPO HERE]"
+ data-repo-id="[ENTER REPO ID HERE]"
+ data-category="[ENTER CATEGORY NAME HERE]"
+ data-category-id="[ENTER CATEGORY ID HERE]"
+ ...
+ </script>
</main>
<Footer />
</Layout>
完成了!您已成功在 AstroPaper 中集成了評論!
帶有亮/暗主題的 React 組件
嵌入佈局中的腳本標籤非常靜態,Giscus 配置(包括 theme)硬編碼到佈局中。鑑於 AstroPaper 具有亮/暗主題切換功能,讓評論隨著網站的其餘部分無縫過渡到亮和暗主題會更好。為了實現這一點,需要更複雜的方法來嵌入 Giscus。
首先,我們將安裝 Giscus 的 React 組件:
npm i @giscus/react
然後我們在 src/components 中創建一個新的 Comments.tsx React 組件:
import Giscus, { type Theme } from "@giscus/react";
import { GISCUS } from "@config";
import { useEffect, useState } from "react";
interface CommentsProps {
lightTheme?: Theme;
darkTheme?: Theme;
}
export default function Comments({
lightTheme = "light",
darkTheme = "dark",
}: CommentsProps) {
const [theme, setTheme] = useState(() => {
const currentTheme = localStorage.getItem("theme");
const browserTheme = window.matchMedia("(prefers-color-scheme: dark)")
.matches
? "dark"
: "light";
return currentTheme || browserTheme;
});
useEffect(() => {
const mediaQuery = window.matchMedia("(prefers-color-scheme: dark)");
const handleChange = ({ matches }: MediaQueryListEvent) => {
setTheme(matches ? "dark" : "light");
};
mediaQuery.addEventListener("change", handleChange);
return () => mediaQuery.removeEventListener("change", handleChange);
}, []);
useEffect(() => {
const themeButton = document.querySelector("#theme-btn");
const handleClick = () => {
setTheme(prevTheme => (prevTheme === "dark" ? "light" : "dark"));
};
themeButton?.addEventListener("click", handleClick);
return () => themeButton?.removeEventListener("click", handleClick);
}, []);
return (
<div className="mt-8">
<Giscus theme={theme === "light" ? lightTheme : darkTheme} {...GISCUS} />
</div>
);
}
這個 React 組件不僅包裝了原生 Giscus 組件,還引入了額外的 props,即 lightTheme 和 darkTheme。利用兩個事件監聽器,Giscus 評論將與網站的主題保持一致,當網站或瀏覽器主題更改時,動態切換亮和暗主題。
我們還需要定義 GISCUS 配置,最佳位置是在 src/config.ts 中:
import type { GiscusProps } from "@giscus/react";
...
export const GISCUS: GiscusProps = {
repo: "[ENTER REPO HERE]",
repoId: "[ENTER REPO ID HERE]",
category: "[ENTER CATEGORY NAME HERE]",
categoryId: "[ENTER CATEGORY ID HERE]",
mapping: "pathname",
reactionsEnabled: "0",
emitMetadata: "0",
inputPosition: "bottom",
lang: "en",
loading: "lazy",
};
請注意,在此處指定 theme 將覆蓋 lightTheme 和 darkTheme props,導致靜態主題設置,類似於之前嵌入 Giscus 的 <script> 標籤的方法。
要完成此過程,將新 Comments 組件添加到 src/layouts/PostDetails.astro(替換上一步中的 script 標籤)。
+ import Comments from "@components/Comments";
<ShareLinks />
</div>
+ <Comments client:only="react" />
</main>
<Footer />
</Layout>
就是這樣!