如何将AI能力与大数据技术结合,助力数据分析治理等工作的效率大幅提升,优化大数据引擎的性能及成本? 了解详情
写点什么

静态博客如何高性能插入评论

  • 2021-01-05
  • 本文字数:3129 字

    阅读完需:约 10 分钟

静态博客如何高性能插入评论

前言


我们知道,静态博客由于不带有动态功能,所以针对评论这种动态需求比较大众的做法就是使用第三方评论系统。第三方评论的本质其实就是使用 JS 去调取第三方服务接口获取评论后动态渲染到页面中。虽然它很好的解决了这个问题,但是由于需要请求接口,在体验上远比动态博客的直出效果要差很多。所以当我把博客从动态博客 Typecho 迁移到静态博客 Hugo 上来时,就一直在思考这个问题。直到我看到了 Hugo 的 getJSON 方法,发现原来静态博客也是能够像动态博客一样直出评论的。


大部分的静态博客的原理是解析存储内容的文件夹,使用一些模板语言遍历数据生成一堆 HTML 文件。而 Hugo 除了解析 Markdown 内容之外,还支持额外的数据获取方法 getJSON。由于有了 getJSON 方法的出现,我们可以实现在博客编译构建过程中动态的去获取评论接口数据,将其渲染到页面中,实现评论数据的直出效果。关于 getJSON 的更多介绍,可以查看 Hugo 文档数据模板[1]一节。


方案


高性能方案基本思路是在需要评论数据的地方通过 getJSON 方法调用接口获取评论数据并进行模板渲染。当评论更新的时候,我们需要触发重新构建。实现这个方案依赖三个关键要素:


  1. 构建过程支持调取接口获取数据

  2. 评论服务提供 HTTP 接口返回数据

  3. 博客部署服务支持钩子触发重新构建


我的博客使用的是 Hugo 静态博客系统,如上文所说通过 getJSON 即可解决第一个问题。而我的评论服务使用的是自研的 Waline[2] 评论系统,它提供了评论数、评论列表、最近评论等基础接口满足我们的数据获取需求。并且 Waline 提供了丰富的钩子功能[3],支持在评论发布的时候触发自第一方法。我的博客部署在 Vercel 上,它提供了 Deploy Hooks[4] 功能,通过 URL 即可触发重新构建。也就是说我只要在 Waline 评论发布的钩子中调用 Vercel 的钩子 URL 触发重新构建即可解决第三个问题。


实现


我的博客上有三处地方和评论有关,分别是首页侧边栏的最近评论,文章标题下方的评论数,以及文章详情页底部的评论列表展示。


最近评论


Waline 最近评论接口:文档[5]


{{ $walineURL := .Site.Params.comment.waline.serverURL }}<h2 class="widget-title ">最近回复</h2><ul class="widget-list recentcomments">  {{ $resp := getJSON $walineURL "/comment?type=recent" }}  {{ range $resp }}  <li class="recentcomments">    <a href="{{.Site.BaseURL}}{{ .url }}">{{ .nick }}</a>:{{ .comment | safeHTML | truncate 22 }}  </li>  {{ end }}</ul>
复制代码


文章评论数


Waline 获取文章对应的评论数接口:文档[6]


{{ $walineURL := .Site.Params.comment.waline.serverURL }}{{ $count := getJSON $walineURL "/comment?type=count&url=/" .Slug ".html" }}<a href="{{ .Permalink }}#comments" title="{{ .Title }}">  <i class="fas fa-comment mr-1"></i>  <span>{{- if gt $resp 0}}{{$resp}} 条评论{{else}}暂无评论{{end -}}</span></a>
复制代码


评论列表


评论列表由于有分页的存在,不像最近评论和评论数一样简单的调用接口即可。先获取评论数,发现有评论时先获取第一页的评论,主要是用来获取总共有多少页评论。之后再从第二页开始循环获取评论数据。最终将获取到的数据全部存到 {{$scratch.Get "comments"}} 数组中,使用模板语法渲染该数组数据即可。


{{$baseUrl := .Site.Params.comment.waline.serverURL}}{{$slug := .Slug}}{{$count := getJSON $baseUrl "/comment?type=count&url=/" $slug ".html" }}{{$scratch := newScratch}}{{$scratch.Add "comments" slice}}
{{if gt $count 0}} {{$comments := getJSON $baseUrl "/comment?path=/" $slug ".html&page=1&pageSize=100"}} {{range $cmt := $comments.data}} {{$scratch.Add "comments" $cmt}} {{end}}
{{$totalPages := $comments.totalPages}} {{if gt $totalPages 1}} {{range $page := seq 2 $totalPages}} {{$comments := getJSON $baseUrl "/comment?path=/" $slug ".html&pageSize=100&page=" $page}} {{range $cmt := $comments.data}} {{$scratch.Add "comments" $cmt}} {{end}} {{end}} {{end}}{{end}}
<div class="vcards"> {{range $cmt := $scratch.Get "comments"}} <div class="vcard" id={{$cmt.objectId}}> <img class="vimg" src="https://gravatar.loli.net/avatar/{{$cmt.mail}}?d=mp"> <div class="vh"> <div class="vhead"> <a class="vnick" rel="nofollow" href="{{$cmt.link}}" target="_blank">{{$cmt.nick}}</a> <span class="vsys">{{$cmt.browser}}</span> <span class="vsys">{{$cmt.os}}</span> </div> <div class="vmeta"> <span class="vtime">{{dateFormat $cmt.insertedAt "2006-01-02 03:04:05"}}</span> <span class="vat">回复</span> </div> <div class="vcontent" data-expand="查看更多..."> {{$cmt.comment | safeHTML}} </div> <div class="vreply-wrapper"></div> <div class="vquote"> {{range $cmt := $cmt.children}} <div class="vh" id="{{$cmt.objectId}}"> <div class="vhead"> <a class="vnick" rel="nofollow" href="{{$cmt.link}}" target="_blank">{{$cmt.nick}}</a> <span class="vsys">{{$cmt.browser}}</span> <span class="vsys">{{$cmt.os}}</span> </div> <div class="vmeta"> <span class="vtime">{{dateFormat $cmt.insertedAt "2006-01-02 03:04:05"}}</span> <span class="vat">回复</span> </div> <div class="vcontent" data-expand="查看更多..."> {{$cmt.comment | safeHTML}} </div> <div class="vreply-wrapper"></div> </div> {{end}} </div> </div> </div> {{end}}</div>
复制代码


构建触发


Waline 在评论发布、更新和删除阶段都支持自定义钩子,在钩子中触发 Vercel 的构建钩子即可完成发布评论重新构建的流程。


按照如下内容修改服务端部署的 index.js 文件,查看文档[7]了解全部的 Waline 钩子。


const Waline = require('@waline/vercel');const https = require('https');const buildTrigger = _ => https.get('https://api.vercel.com/v1/integrations/deploy/xxxxx');
module.exports = Waline({ async postSave(comment) { if(comment.status !== 'approved') { return; } buildTrigger(); }, async postUpdate() { buildTrigger(); }, async postDelete() { buildTrigger(); }});
复制代码


后记


通过以上操作,就能在不损失用户体验的情况下实现评论数据的动态支持了。有些人可能会担心是否会在构建阶段造成超多的接口请求。这里大可不用担心,Hugo 自己会在构建的时候做接口的缓存,同 URL 的接口调用会走缓存数据而不会重新调用。


除了用户体验之外,由于只会在构建的时候触发数据的获取,针对有调用次数配额的第三方评论服务也能节省额度。当然,理论上构建次数是远小于访问次数的,所以额度节省的结论是能成立的。如果说你的构建次数要比访问次数还要大的话,那这种方法就无法节省额度了。


当然这种方式也会有带来些问题,主要是评论的更新没那么快。好在 Hugo 的构建速度非常快,一两分钟的时间也能接受。而针对用户评论的发布,则可以通过评论发布后先假插入缓解该问题。


文章转载自:360 技术(ID:qihoo_tech)

原文链接:静态博客如何高性能插入评论


2021-01-05 08:00810

评论

发布
暂无评论
发现更多内容

Kubernetes fror Flink 硬气功实践

CTO技术共享

flink 个人成长 10 月月更

团队实现知识管理,先从知识库做起!

Baklib

效率 效率工具 知识管理 团队 知识

华为架构师亲手操刀,世界五百强都在用的kafka也就那么回事

程序知音

Java kafka 架构 后端技术

EMQ x 阿里云:云上高效构建,IoT 数据一站处理|直播预告

阿里云弹性计算

物联网 IoT 计算巢

NFT卡牌链游系统开发Web3游戏技术

薇電13242772558

dapp web3

Vue组件入门(十)Attributes 继承

Augus

Vue 3 10月月更

来了!2022 XDR网络安全运营新理念峰会即将开幕!

未来智安XDR SEC

网络安全

SAP | Local结构和Global结构

暮春零贰

SAP 结构 10月月更

一起学习 Go 语言设计模式之单例模式

宇宙之一粟

设计模式 单例模式 Go 语言 10月月更

行业方案|数字化疫情防控运行保障解决方案

云智慧AIOps社区

性能优化 安全 监控 运维管理 IT解决方案

SAP | abap的数据对象

暮春零贰

SAP 10月月更 数据对象

知识经济时代,企业该如何进行知识管理?

Baklib

效率工具 知识管理 企业 知识 知识经济

技术使用点-mixins的使用

默默的成长

前端 Vue 3 10月月更

超级app+轻应用带来的改变

Geek_99967b

小程序

谷歌?新手不推荐 选它就对了

清风无影

前端 工具 浏览器 谷歌 10月月更

vivo 鲁班平台 RocketMQ 消息灰度方案

阿里巴巴云原生

阿里云 云原生 Apache RocketMQ

数据产品经理那点事儿四

松子(李博源)

大数据 深度思考 高效工作 数据产品经理

navicat的使用与数据库的DML操作

渔戈

MySQL SQL语句 10月月更

ElasticSearch + Kibana for Kubernetes 硬气功实践 2

CTO技术共享

elasticsearch 个人成长 10 月月更

开源日志收集 肿么选型??

CTO技术共享

个人成长 log 10 月月更

手把手教你成为荣耀开发者:如何进行注册与认证?

荣耀开发者服务平台

开发者 手机 新手指南 荣耀 honor

秒云入选2022年成都市新经济梯度培育企业

秒云

成都市新经济梯度培育企业

外包和自研应该选择呢?教你三招选出最合适自己的平台

千锋IT教育

打破汽车零部件企业供应链壁垒,数商云SCM供应链系统实现一体化采购协同

数商云

数字化转型 供应链 企业数字化

真·workshop,来自联通、移动、爱奇艺等14位资深专家与你面对面聊云原生硬核技术|2022云栖大会

OpenAnolis小助手

云原生 虚拟化 云栖大会 龙蜥社区 专场

数据分析有 AI 帮你,Sugar BI 智能分析全场景介绍

百度智能云

数据分析 可视化 BI

你会用Go语言的rune类型吗?

王中阳Go

Go golang 学习方法 数据处理 10月月更

手把手完成智慧路灯的开发,完成设备上云【华为云IoT】

DS小龙哥

10月月更

分布式事务-引出分布式事务

zarmnosaj

10月月更

ERP外贸管理系统是什么?哪家好?如何选?

优秀

外贸管理 ERP系统 ERP外贸管理系统

【Java深入学习】一个关于“锁”的程序-上

Geek_65222d

十月月更

静态博客如何高性能插入评论_文化 & 方法_360技术_InfoQ精选文章