最近在对博客进行性能分析时,发现 Twikoo 评论系统的加载机制存在一些性能瓶颈。为了提升首屏加载速度(LCP)和改善用户体验,我进行了一系列的优化操作。以下是具体的优化过程记录。

1. 问题分析

在优化前,博客的评论系统加载逻辑存在以下问题:

  1. 资源重复加载:Twikoo 的核心 JS 库 (twikoo.all.min.js) 在文章页模板 (single.html) 和评论区模板 (comments.html) 中被多次引用。
  2. 阻塞渲染:Script 标签默认是同步加载的,这会阻塞后续 DOM 的解析和渲染,拖慢首屏展示时间。
  3. 加载时机过早:评论功能虽然重要,但在页面加载初期并非最高优先级内容。原有的写法在 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)也需要等待。我将初始化代码封装在 windowload 事件监听器中。

这样,只有当页面的所有资源(包括图片、样式表等)都完全加载完毕之后,才会开始执行评论系统的初始化。

修改后的 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. 优化结果

经过上述调整:

  1. 减少了 HTTP 请求:消除了一次多余的 JS 库请求。
  2. 不阻塞渲染:JS 加载和执行完全移出了关键渲染路径(Critical Rendering Path)。
  3. 提升 PageSpeed 分数:由于减少了主线程阻塞,LCP 和 TBT(总阻塞时间)指标得到了显著改善。

现在,页面的核心内容(文章正文)能够以最快速度呈现在读者面前,而评论区则会优雅地在后台静默加载完成。