主页关于链接归档相册

关于主题安装 InstantClick 的二三事

代码

实际上之前写 Lightime 的时候就折腾过这东西,而且也写过一篇文章记录过。当时用了最无脑的方式解决了各种问题。这次不是从零写主题而是修改别人的主题,所以动起手来不如自己写的主题那样自在。


InstantClick 简介

  1. Github项目地址:https://github.com/dieulot/instantclick
  2. 官网:http://instantclick.io/
  3. 文档: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 里的小改一下就完成了

the end.