Loading 4%

Disqus 留言板的實作【3】

靜態部落格的留言功能需要外掛支援。我在 Giscus 與 Disqus 中選擇了 Disqus,並整理導入過程中的問題與解法,提供給想在文章頁加入留言功能的人參考。

為什麼文章內頁加入留言功能

前面的文章提到如何建立文章內頁,主要是把內容以靜態方式呈現在畫面上。但在規劃網站時我也思考過,如果只有分享、沒有回應,其實互動感會少很多。 我希望 「分享」是可以互相的。當讀者看完後,無論是好的建議或不同想法,都能留下回饋,對寫的人來說是一種紀錄與延續創作動力

網站外掛留言板的原因

在建立文章時,我使用 Nuxt Content 管理靜態內容,並沒有把文章存進資料庫。因此在個人網站的規劃上,本來就沒有後端資料庫用來保存留言

留言要存在哪裡?因此我選擇使用外掛式留言服務,以 JavaScript 載入評論系統,將留言資料交由第三方平台管理,讓靜態文章頁也能具備留言互動功能,而不用額外維護後端與資料庫。

Giscus vs Disqus:我的選擇考量

Giscus

Giscus 是建立 GitHub Discussions 的留言系統,可以把系統整合到文章內頁。當使用者留言時,內容會同時出現在網站與 GitHub Discussions 中。

對開發者來說可以把資料直接存在 GitHub,不需要自己處理。

優點:沒有廣告、樣式可自訂、留言與 GitHub Discussions 同步管理

缺點:必須登入 GitHub 才能留言、需要程式基礎才能開發

Disqus

Disqus 是個整合評論技術平台,在許多部落格與討論型網站都能看到它的身影。

它支援多平台快速導入,也提供多種第三方登入方式,對一般訪客較友善。不過免費方案會插入廣告,需要取捨。

優點:支援多平台快速導入、提供多種第三方登入

缺點:會出現廣告,會影響載入速度與閱讀體驗

我的選擇

我最後選擇 Disqus 。兩者在技術上都能整合,但真正影響我的是使用者登入門檻

如果只是想留言,卻必須先註冊或登入 GitHub,對一般訪客來說門檻比較大,也可能直接放棄留言,相較之下,Disqus 支援 Google、Facebook、X 等第三方登入,使用上比較友善。

因此我會在意訪客是否願意參與,而不只是技術面客製或影響速度,這也是我選擇 Disqus 的原因。

選擇小建議 技術型網站適合 Giscus;希望更多一般使用者互動,Disqus 會更合適。

文章內頁建立 Disqus 留言板

Disqus 建立帳號並設定網站

到 Disqus 官網註冊後,進入後台建立一個新的 Site,讓 Disqus 知道留言要掛在哪個網站上。

流程大致如下:

  1. 官方註冊/登入帳戶
  2. Site Admin → Your Sites → New 建立網站
  3. 填寫網站資料並選擇免費 Basic 方案
  4. 填寫網站設定
  5. 平台選擇 Universal Code (Nuxt 未在內建平台列表) 取得 Disqus 提供的通用程式碼貼入專案,就能在頁面中載入 Disqus 留言板。

文章載入留言板

個人網站使用 Nuxt 框架,Disqus 提供的 Universal Code 需要稍微調整後,才能在元件中正確載入,因此我先建立元件來處理初始化流程:

Disqus/index.vue
      <script setup lang="ts">
// ... disqusConfig
const loadDisqus = () => {
  if (loaded.value) return;

  window.disqus_config = disqusConfig;

  const script: HTMLScriptElement = document.createElement('script');
  script.src = 'https://<Disqus 設定網站名稱>.disqus.com/embed.js';
  script.setAttribute('data-timestamp', String(+new Date()));

  setTimeout(() => {
    document.head.appendChild(script);
    loaded.value = true;
  }, 1000);
}

onMounted(() => {
  loadDisqus();
});
</script>
<template>
  <div id="disqus_thread"></div>
</template>

    

不同文章設定留言板

根據官方 JavaScript 的設定,我主要設定三個參數來對應每一篇文章:

  1. this.page.identifier: 文章唯一識別。 即使未來更換網域,也能保持留言不遺失。若未設定,Disqus 會直接用 URL 當識別。
  2. this.page.url: 文章完整路徑。 建議設定成絕對路徑,避免在有參數,載入錯誤留言。
  3. this.page.title: 文章標題。
Disqus/index.vue
      <script setup lang="ts">
const disqusConfig = () => {
  // ...cleanIdentifier: Nuxt Content 預設 id 會是 posts/posts/1.XXX.md,使用正規只留下文章別名
  return {
    identifier: cleanIdentifier,
    url: `${runtimeConfig.public.SITE_URL}${route.path}`,
    title: props.title
  };
};
// ... loadDisqus
</script>

    

設定好後,就能在每篇文章內頁看到對應的留言區塊。

導入 Disqus 遇到的問題與解法

在文章頁載入 Disqus 留言板後測試時,我發現切換 Color Mode(亮 / 暗色)時,留言板的顏色不會跟著更新。

雖然 Disqus 後台有提供「自動偵測顏色」設定,但實際檢查後會發現,Disqus 是透過判斷頁面 body 是否帶有 class="dark" 來決定主題樣式。

而這個判斷只會在初始化時執行一次,所以後續切換 Color Mode,留言板並不會自動跟著更新。

解法:路由與 Dark Mode 的處理

因為 Disqus 在第一次載入時就固定了樣式,所以當網站切換主題時,需要手動讓留言板重新初始化。

我做法清空原有 Disqus 元素設定後再重新載入留言板:

Disqus/index.vue
      <script setup lang="ts">
const reloadDisqus = async (): Promise<void> => {
  await nextTick();
  // ...清空 Disqus 容器元素
  // ...找到並移除 Disqus 設定
  
  // 重置載入狀態
  loaded.value = false;
  // 等待 1 秒後重新載入 Disqus
  setTimeout(() => {
    loadDisqus();
  }, 1000);
};

watch(colorMode, async () => {
  await reloadDisqus();
});
</script>

    

總結

留言板是我在網站中唯一使用的外掛套件。從一開始挑選方案、評估是否能正確載入與使用,到實際導入後會不會和現有功能衝突,這些都是開發過程中需要一一確認的地方。

在目前的維護階段,回頭看以前寫的程式與設定,也常會發現當初沒有考慮完整的地方,再逐步補上與修正。對我來說,這些調整是很寶貴的實戰經驗。

下一篇會開始整理網站 SEO 的設定方式,包含 Meta 設計、檢視方式,以及我如何透過 Nuxt SEO 套件做進一步優化,有興趣的話可以繼續往下看!(待我上稿 XD)

留言板