VuePress 集成第三方评论模块

发布于 2023-07-22 22:31:38 字数 4452 浏览 29 评论 0

VuePress 是一个 Vue 驱动的静态网站生成器,用来写文档的体验很好,本站就是基于 VuePress 的。VuePress 官方正在开发针对博客的优化功能 Blog Support roadmap ,已经有人在喊建议集成 disqus(ps:disqus 已经被墙)了,有兴趣的同学可以去投个票。

在官方之前,大家也可以参考本文为自己的博客/文档添加评论模块。

本文采用 Gitalk 作为示例,效果看文章底部。如果想集成其它第三方模块,本文代码也有一定参考性。

注意:Gitalk 要求用户登录 github 才能评论

注册 OAuth application

参考 gitalk ,本博客下的评论区即是 gitalk,你会得到一个 client ID 和一个 client secret,这个将被用于之后的用户登录。

创建或准备一个 github 仓库存储评论

Gitalk 将评论都存储在仓库 issue 中,同时要求用户登录 github 才能评论,所以需要先准备一个仓库。 本博客托管在 Github Pages 上,所以直接使用 hughfenghen.github.io 仓库 来存储评论了。

创建一个 enhanceApp.js 文件

./vuepress 目录下创建 enhanceApp.js 文件, copy 以下代码到文件中,填写代码中的 xxx 部分。 如果已存在 enhanceApp 文件,则 copy try...catch 代码块和 integrateGitalk 函数

// 重试
function tryRun (fn, times = 3) {
  let execCount = 1
  
  fn(next)

  function next(delay) {
    if (execCount >= times) return
    setTimeout(() => {
      execCount += 1
      fn(next)
    }, delay);
  }
}

function integrateGitalk(router) {
  const linkGitalk = document.createElement('link')
  linkGitalk.href = 'https://unpkg.com/gitalk  @1/dist/gitalk.css'
  linkGitalk.rel = 'stylesheet'
  const scriptGitalk = document.createElement('script')
  scriptGitalk.src = 'https://unpkg.com/gitalk  @1/dist/gitalk.min.js'

  document.body.appendChild(linkGitalk)
  document.body.appendChild(scriptGitalk)

  router.afterEach((to, from) => {
    // 页面滚动,hash 值变化,也会触发 afterEach 钩子,避免重新渲染
    if (to.path === from.path) return
    
    // 已被初始化则根据页面重新渲染 评论区
    tryRun((next) => {
      const $page = document.querySelector('.page')
      if ($page && window.Gitalk) {
        // 如果不 setTimeout 取到是上一篇文档的标题
        setTimeout(() => {
          renderGitalk($page, to.path)
        }, 1);
      } else {
        next(500)
      }
    }, 10)
  })

  function renderGitalk(parentEl, path) {
    // 移除旧节点,避免页面切换 评论区内容串掉
    const oldEl = document.getElementById('comments-container');
    oldEl && oldEl.parentNode.removeChild(oldEl);

    const commentsContainer = document.createElement('div')
    commentsContainer.id = 'comments-container'
    commentsContainer.classList.add('content')
    commentsContainer.style = 'padding: 0 30px;'
    parentEl.appendChild(commentsContainer)

    const gitalk = new Gitalk({
      clientID: 'xxx', // 第一步注册 OAuth application 后获取到的 Client ID
      clientSecret: 'xxx', // 第一步注册 OAuth application 后获取到的 Clien Secret
      repo: 'hughfenghen.github.io',
      owner: 'hughfenghen',
      admin: ['hughfenghen'],
      id: location.pathname,      // Ensure uniqueness and length less than 50
      distractionFreeMode: false  // Facebook-like distraction free mode
    })
    gitalk.render('comments-container')
  }
}

export default ({
  Vue, // VuePress 正在使用的 Vue 构造函数
  options, // 附加到根实例的一些选项
  router, // 当前应用的路由实例
  siteData // 站点元数据
}) => {
  try {
    // 生成静态页时在 node 中执行,没有 document 对象
    document && integrateGitalk(router)
  } catch (e) {
    console.error(e.message)
  }
}

enhanceApp 参考文档

VuePress deploy

部署项目,如果还未部署,请参考 部署文档

注意事项

  • VuePress 构建的时候,在 node 中执行代码生成各个页面的时候,此时 document 为 undefined,所以写在 try...catch 块中,构建时必然会执行到 catch 块代码。目前没找到环境检测方法。
  • document.querySelector('.page') ,page、content 是 VuePress 现在默认的 class,后续升级可能会报错,届时需要同步改一下。
  • 如果需要对本文提供的代码进行改造, renderGitalk 在每次路由切换后都必须执行,Gitalk 的 ID 是页面的 fullPath,如果未执行会导致页面间评论混乱。
  • 评论之后刷新页面,如果发现评论不见了,是因为页面缓存,不用担心,可以点击 Issue Page(Like 右侧)检查。

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据

关于作者

JSmiles

生命进入颠沛而奔忙的本质状态,并将以不断告别和相遇的陈旧方式继续下去。

0 文章
0 评论
84960 人气
更多

推荐作者

qq_E2Iff7

文章 0 评论 0

Archangel

文章 0 评论 0

freedog

文章 0 评论 0

Hunk

文章 0 评论 0

18819270189

文章 0 评论 0

wenkai

文章 0 评论 0

    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文