Lazyload 不让 Valine 评论组件拖慢页面加载

2020-03-13 技术向
Cover Image

我一直将速度作为衡量一个网站的重要指标。就算一个网站再精美,但每个动作都要花上 10s 来完成,想必体验也不会好到哪去。而即便 Valine 作为一款简介强大的评论组件,按目前效果来看也仍然有着可观的优化空间。

老朋友 lazyload

Lazyload 在前端性能优化领域已是老生常谈,为了不让一些非关键资源和主要内容争夺带宽和性能,任何媒体资源、DOM 节点、非关键 JS 和 CSS 都可以使用 lazyload 优化。

而 Lazyload 的实现也非常简单,用一个 JavaScript 监控当前页面位置,当元素出现或即将出现在可视区域时才加载资源,而非传统的一上来就把所有资源加载完。

现在是公元 2020 年,还有相当一部分插件绑定 scroll 事件实现 lazyload ,在页面滚动的时候这个函数会被频繁触发,十分浪费性能。相比之下,调用 IntersectionObserver 则是一种更优雅的解决方案,这个 API 会自动「观察」元素是否在可视范围内,早在 Chrome 51 便支持了这一功能,其他现代浏览器也均有支持。除非你真的很在意旧版 IE 用户,不然都建议使用后者。

(IntersectionObserver 浏览器支持情况)

Valine ? Yes !

市面上主流的静态博客评论插件其实并不算很多,像是我在使用的 Hexo 主题 Volantis 就适配了 Gitalk, Disqus, Valine 和 Livere 。

可是可能是最老牌好用的 Disqus 已经被墙,尽管有人开发了 DisqusJS 但是需要注册登录才能评论的体验还是有点割裂。 韩国的 Livere 来必力也是需要注册登录才能评论,而且国内访问速度一般,绝对称不上优秀。Gitalk / Gitment 必须要使用 GitHub 账号才能评论,而且受到 GitHub Issue Label 的限制,后端管理也不方便。

最后我还是选择了 Valine ,界面简洁,基于免费版的 LeanCloud 就能轻松跑起,配合 Valine Admin 插件也能获得还说得过去的管理后台。

确实,相较于 Disqus 和 Livere ,Valine 的加载速度已经优秀得太多了。但是 Gravatar 头像在国内即便加了第三方 CDN 速度还是不敢恭维,而且全 markdown 语法支持也让插入大量媒体内容成为可能,甚至这些媒体内容还不遵循文章板块的 lazyload 。尽管这些不能一味把锅甩给 Valine ,但是确实让我某个页面的资源加载大小从 600K 增至 2M ,加载时间从 2s 增至 3.7s 。

而我在谷歌搜索「valine + lazyload」的关键词时,清一色都是关于加入 Valine 评论插件和图片 lazyload 这些揉在一起的教程,完全没有我真正要找的让 ValineJS 本身 lazyload 的插件。

好吧,既然 lazyload 实现也不复杂,那我就自己写一个。

Lazyload 在 Valine 上实践

Valine 是在加载了 Valine.js 后调用 init 方法来进行用户初始化的。如果仅仅是将 Valine.js 换成 lazyload JS 的话势必会导致依赖问题。考虑到博客即便有许多页面,每个页面的 Valine 配置其实都是一致的,所以我的想法是使用一个专门的 JS 如 valine_config.js 单独放置初始化内容:

'use strict'

var valine = new Valine();
valine.init({
el: '#valine_container',
appId: '<APP_ID>',
appKey: '<APP_KEY>',
notify: false,
verify: false,
avatar: '',
placeholder: 'just go go'
});

配置记得换成自己的,细节可以看 这里

然后就是 lazyload JS 了,代码很短,我写的只有 30 几行,你可以尝试着自己实现一下。要注意下加载的顺序,默认可不是按照填放的顺序加载,特别是这些相互依赖的部分。

接下来就上代码:

'use strict'

function addScript(url) {
var s = document.createElement('script');
s.setAttribute('src', url);
s.async = false
document.body.appendChild(s);
}

function loadValine() {
addScript('https://unpkg.com/valine/dist/Valine.min.js');
addScript('{ your config path }');
}

var runningOnBrowser = typeof window !== "undefined";
var isBot = runningOnBrowser && !("onscroll" in window) || typeof navigator !== "undefined" && /(gle|ing|ro|msn)bot|crawl|spider|yand|duckgo/i.test(navigator.userAgent);
var supportsIntersectionObserver = runningOnBrowser && "IntersectionObserver" in window;

setTimeout(function () {
if (!isBot && supportsIntersectionObserver) {
var io = new IntersectionObserver(function(entries) {
if (entries[0].isIntersecting) {
loadValine();
io.disconnect();
}
});
io.observe(document.getElementById('{ your Valine container ID }'));
} else {
loadValine();
}
}, 1);

博主毕竟 是个 OIer ,有些编程基础。一两个月前自学了点 JavaScript ,这是我尝试写的第一个还算有点样子的东西,大家轻喷。目前还需要下载下来手动改代码才能用上,看看后续能不能通过 NPM package 的方式更方便的用上,当然我还有很多东西要学。

这是我花了一个中午写出来的,中途也遇到了问题。也许这点东西让别人来写可能就 10 分钟搞定的事,我却花了 1 个多小时。而且受 苏卡卡大佬Disqus Lazyload 影响很大。

但是我觉得,在遇到问题并尝试解决,是我进步最快的时候。这是那些「教程」帮不了你的,无论是遇到问题时需要学习的新手段,还是就 debug 本身的思路,你啃半天书都不如试着自己写点东西来的实在。

可能不只是编程,许多事情都应该不断实践,只有踩下去的坑才能更好的填。所以,如果你有好的想法,赶紧把它做出来,即便一次又一次失败,又如何呢?这本身就是一种超越了。

祝大家周末愉快!


(完,感谢阅读!)

本文作者:ChrAlpha

文章默认使用 CC BY-NC-SA 4.0 协议进行许可,使用时请注意遵守协议。

本文链接: https://blog.ichr.me/post/valine-lazyload/

技术向

评论

您所在的地区可能无法访问 Disqus 评论系统,请切换网络环境再尝试。