关于主题安装 InstantClick 的二三事
实际上之前写 Lightime 的时候就折腾过这东西,而且也写过一篇文章记录过。当时用了最无脑的方式解决了各种问题。这次不是从零写主题而是修改别人的主题,所以动起手来不如自己写的主题那样自在。
InstantClick 简介
- Github项目地址:https://github.com/dieulot/instantclick
- 官网:http://instantclick.io/
- 文档:http://instantclick.io/documentation
版本
不知道为什么 JSdelivr 上的 InstantClick 有多个版本,对比了下貌似是第三方上传的,不是原汁原味。刚开始直接用的最新版 3.1.0-2
,一番操作后发现,*我超?我的德芙般顺滑的加载进度条呢?*找了下才发现这个版本后面多了个 -2
,于是切回 3.1.0
。发现加载进度条有了,看着就舒服很多。
又打开 F12,发现了一堆报错,然后随便对比了下源码,发现和 GitHub 上的不太一样,后面多了条 module.exports = InstantClick
,不是很懂这个 module.exports
怎么操作,又作罢。
尝试直接使用原版,又发现进度条的 <style>
无法自动删除,还在疯狂增值。最后不想研究了还是选择了 3.1.0-2
。感觉没有进度条还是有点小卡的样子。就这样吧,之后可能闲着了会自己写一个加上。
然后我又换回 Lightime 了,加载进度条回来了。针不戳
代码高亮
第二个问题就是主题自带的代码高亮,CSS 是写在 <head>
里的,而且加了条检测当前是否在文章页的判断。 InstantClick 默认只会改变 <title>
和 <body>
的内容。总之如果你是从其他页面进入文章页的,InstantClick 不会改变<head>
,也就不会加上代码高亮的 CSS。
我不想直接把这段 CSS 放在 post.ejs
里,我也不想直接全局加上这个 CSS,感觉会变肥。
这里用了个比较无脑的方法。 InstantClick 可以在 html 标签里加上 data-instant-track
,他就会自动检测这标签里的变化。于是代码变成了这样:
<data-instant-track>
<% if (config.highlight.enable) { %>
<!-- Prettify Theme -->
<%- partial('_plugin/highlight/hexo-hljs/theme') %>
<% } %>
</data-instant-track>
直接括起来,写到这里越看越无脑( ̄▽ ̄)"
貌似加了这个 data-instant-track
会被直接安排到 <body>
里,你现在打开 F12 应该可以看到 <body>
里的 <data-instant-track>...</data-instant-track>
,感觉有点不美观,而且有可能造成重复加载(我瞎说的我也不知道会不会)。之后可能还得改改。
草,写完文章 hexo s
检查的时候发现 <body>
里多了一堆 <meta>
,之后确实得改改。
评论加载
这也是个经典问题,大致就是 InstantClick 只会更换内容,但不会自动加载 JS。之前 Lightime 使用的是直接加按钮,点击加载评论的方法。这次从 Sukka大佬 那里复制了份代码。《使 Disqus 不再拖累性能和页面加载》
function loadDisqus() {
// Disqus 安装代码
var d = document, s = d.createElement('script');
s.src = 'https://[你的 Disqus shortname].disqus.com/embed.js';
s.setAttribute('data-timestamp', +new Date());
(d.head || d.body).appendChild(s);
window.disqus_config = function () {
this.page.url = [你的页面 URL];
this.page.identifier = [你的页面的唯一辨识符];
};
// 如果你和我一样在用 DisqusJS,loadDisqus() 里就应该是 DisqusJS 的初始化代码 new DisqusJS({...})
}
// 通过检查 window 对象确认是否在浏览器中运行
var runningOnBrowser = typeof window !== "undefined";
// 通过检查 scroll 事件 API 和 User-Agent 来匹配爬虫
var isBot = runningOnBrowser && !("onscroll" in window) || typeof navigator !== "undefined" && /(gle|ing|ro|msn)bot|crawl|spider|yand|duckgo/i.test(navigator.userAgent);
// 检查当前浏览器是否支持 IntersectionObserver API
var supportsIntersectionObserver = runningOnBrowser && "IntersectionObserver" in window;
// 一个小 hack,将耗时任务包裹在 setTimeout(() => { }, 1) 中,可以推迟到 Event Loop 的任务队列中、等待主调用栈清空后才执行,在绝大部分浏览器中都有效
// 其实这个 hack 本来是用于优化骨架屏显示的。一些浏览器总是等 JavaScript 执行完了才开始页面渲染,导致骨架屏起不到降低 FCP 的优化效果,所以通过 hack 将耗时函数放到骨架屏渲染完成后再进行。
setTimeout(function () {
if (!isBot && supportsIntersectionObserver) {
// 当前环境不是爬虫、并且浏览器兼容 IntersectionObserver API
var disqus_observer = new IntersectionObserver(function(entries) {
// 当前视窗中已出现 Disqus 评论框所在位置
if (entries[0].isIntersecting) {
// 加载 Disqus
loadDisqus();
// 停止当前的 Observer
disqus_observer.disconnect();
}
}, { threshold: [0] });
// 设置让 Observer 观察 #disqus_thread 元素
disqus_observer.observe(document.getElementById('disqus_thread'));
} else {
// 当前环境是爬虫、或当前浏览器其不兼容 IntersectionObserver API
// 直接加载 Disqus
loadDisqus();
}
}, 1);
把 loadDisqus
里的小改一下就完成了