最近在对博客进行性能分析时,发现 Twikoo 评论系统的加载机制存在一些性能瓶颈。为了提升首屏加载速度(LCP)和改善用户体验,我进行了一系列的优化操作。以下是具体的优化过程记录。
1. 问题分析
在优化前,博客的评论系统加载逻辑存在以下问题:
- 资源重复加载:Twikoo 的核心 JS 库 (
twikoo.all.min.js) 在文章页模板 (single.html) 和评论区模板 (comments.html) 中被多次引用。 - 阻塞渲染:Script 标签默认是同步加载的,这会阻塞后续 DOM 的解析和渲染,拖慢首屏展示时间。
- 加载时机过早:评论功能虽然重要,但在页面加载初期并非最高优先级内容。原有的写法在 HTML 解析到评论区时就立即请求网络资源并执行初始化,抢占了文章正文渲染的资源。
2. 优化方案
针对上述问题,实施了以下三个维度的优化:
2.1 全局单次异步加载
首先,从原本的模板中移除了所有硬编码的 <script src="..."> 标签。改为在全局页脚扩展模板 layouts/partials/extend_footer.html 中统一引入,并添加 defer 属性。
defer 属性告诉浏览器:该脚本可以并行下载,但必须等到 HTML 解析完成后、DOMContentLoaded 事件触发前才执行。
{{- /* layouts/partials/extend_footer.html */ -}}
{{- if .Site.Params.twikoo -}}
<script defer src="https://cdn.staticfile.org/twikoo/{{ .Site.Params.twikoo.version | default "1.6.40" }}/twikoo.all.min.js"></script>
{{- end -}}
2.2 延迟初始化逻辑
仅仅延迟加载 JS 文件是不够的,初始化的 JS 代码(调用 twikoo.init)也需要等待。我将初始化代码封装在 window 的 load 事件监听器中。
这样,只有当页面的所有资源(包括图片、样式表等)都完全加载完毕之后,才会开始执行评论系统的初始化。
修改后的 layouts/partials/comments.html:
<script>
window.addEventListener('load', function() {
twikoo.init({
envId: {{ .Site.Params.twikoo.id }},
el: "#tcomment",
lang: 'zh-CN',
// ...其他配置
})
});
</script>
2.3 评论数统计的异步化
对于文章顶部的“评论数”显示,逻辑也做了同样的更改。虽然这可能会导致评论数字出来的稍微晚零点几秒,但换来的是文章标题和正文的秒开。
修改后的 layouts/_default/single.html:
<script>
window.addEventListener('load', function() {
// ... 获取当前 URL 逻辑
twikoo.getCommentsCount({
// ...配置参数
}).then(function (res) {
// ...更新 DOM
});
});
</script>
3. 优化结果
经过上述调整:
- 减少了 HTTP 请求:消除了一次多余的 JS 库请求。
- 不阻塞渲染:JS 加载和执行完全移出了关键渲染路径(Critical Rendering Path)。
- 提升 PageSpeed 分数:由于减少了主线程阻塞,LCP 和 TBT(总阻塞时间)指标得到了显著改善。
现在,页面的核心内容(文章正文)能够以最快速度呈现在读者面前,而评论区则会优雅地在后台静默加载完成。
...