本博客优化点总结 (一) - js 字体 归档 评论系统 CDN

Website Feb 18, 2017

修订记录

  • 2021.01.05 - 更新部分内容
  • 2017.02.18 - 初稿完成

这篇文章篇幅过长并且过于杂乱,2021 年我又开了个新坑 本博客优化点总结 (二) - Ghost 路由 RSS 暗黑模式 闪白屏,针对 Ghost 博客做了一些优化,并且完美处理了暗黑模式下闪白屏的问题。

储存模块

最早是自己写了一个可以上传图片到 upyun 的插件,pupboss/ghost-upyun-store。现在已经改用腾讯云。

链接优化

在文章内超链接的前面加上小图标,详细功能参考下面列表:

优化文章内链接

外部链接使用新 tab 打开。用 DOM 选择器遍历一下整个文档即可。

$(document.links).filter(function() {
    return this.hostname != window.location.hostname;
}).attr('target', '_blank');

// 或者

var links = document.links;
for (var i = 0; i < links.length; i += 1) {
  if (links[i].hostname && links[i].hostname != window.location.hostname) {
    links[i].target = '_blank';
  }
}

字体优化

  • 使用 bramstein/fontfaceobserver 来管理外部字体的加载
  • 使用 jrnewell/goog-webfont-dl 把谷歌字体下载到本地,虽然谷歌字体能访问了,根据测试,移动网络还是连不通,为了妥协,还是将字体放到本地吧
  • 使用尽可能少的 font-family,减少 CSS 下载时间
  • 加入一个标识符,如果 web 字体下载成功,就用 web 字体,如果没有,就调用系统内置字体

拆分大的 js 或者合并太碎的 js

现代浏览器支持同时下载多个 js 文件,把 js 拆分成 2-3 个可以提高性能。但是如果你的 js 文件过于零碎,最好考虑把它们合并起来,以减少频繁网络请求带来的延迟。

如果你有遇到过大 js 在 Nginx 里面下载不下来的问题,可以参考如下推特。

实际上是因为 Nginx 错误配置,导致缓存区无权限读写 - https://twitter.com/isjetl/status/1350725012550868995

精简 FontAwesome

FontAwesome 的字体体积还是有点大。如果有条件还是建议自己造 icon ,还方便前文说的网站小图标。另外某些去广告插件会屏蔽 social icon,自己造 icon 还有个好处就是可以避免这种情况。

Fanboy's Social Blocking List 这个规则简直丧心病狂,icon-github 这种 icon 也会被屏蔽掉。更要命的是在某些情况下,这个规则是默认加载到 AdBlock 的 – https://twitter.com/isjetl/status/1346393859580784641

加入了 ToC

使用的是 idiotWu/jQuery-TOC 这个插件。

Archive 功能

无耻的移植了xiaoluoboding/ghost-theme-kaldorei的创意。

评论系统

早期用的是 Disqus,因为它在国内被墙的缘故,当时出现过一些状况, async 加载模式下会阻塞页面渲染,只有超时失败之后才渲染出文字。后来解决了这个问题,如果有同样问题的朋友,可以参考最后一个小标题。

现在改用 Valine 方案,因为不需要后端,又能满足需求。

Google Analytics

最开始统计是放到服务器端的,GA 配合 Nginx,因为阿里云和 Google Analytics 还是很畅通的,但是问题就是导致统计的信息不全,最后还是放到了网页上,牺牲了一定的加载速度。

全站放到 CDN

我使用的是腾讯云的 CDN,性能还不错,挑不出毛病,价格也合理。详细可以参考这篇:全站 CDN 的选择和配置经验分享

图片压缩

ImageOptim,最强大的压缩软件,没有之一。又拍云的压缩功能损失略大,反正我不能接受,效果不如这款软件。手动压缩后再上传 CDN,虽然略微麻烦一些,但是效果还是不错的。

图片 Lazy Load

以前用过 tuupola/jquery_lazyload 这个插件,实现图片的懒加载,改进用户体验。但是最后发现这是大坑一个,RSS 或者其他方式访问的话,图片不会被加载。结论就是流量不值钱,不要使用这个方案实现懒加载。如果真的想折腾,可以看看划到图片位置才显示的方案。

HTTPS & HTTP/2

  • Let's Encrypt 的证书,自动更新
  • Nginx 1.10.3 使用的是 dotdeb 编译的 Nginx,编译时加入了新版的 openssl,可以支持 HTTP/2。 Nginx 默认已经支持 HTTP/2。

HSTS & OCSP Stapling

这就属于 Nginx 的配置范畴了,具体可以看 Nginx 配置上更安全的 SSL & ECC 证书 & Chacha20 & Certificate Transparency

HSTS Preloading

可以在这个网站上面提交你的网址 HSTS Preload List Submission,最后会加入到 Chrome 的 Preloading 列表,实现直接访问 HTTPS,而不是从 HTTP 跳转,可以有效预防劫持。

附录:外部资源引用

这里主要是说在别人服务器上的,尤其是被 GFW 的外部资源。当然了,不只限于 JS 文件,CSS,图片什么的都可以,原理大同小异。

我的博客上面的资源,几乎所有的 JS,图片,都在自己的 CDN,其他的在 VPS,只有 Google Analytics 和 Disqus 引用的第三方 JS。

事情需要从这个博客的 Theme,Namjagbarwa 说起,首页的 card 在 layout 之前,需要保证所有外部资源加载完毕,其代码类似于这样:

$(window).load(function() {

  window.sr = window.ScrollReveal().reveal(cardName, {
      afterReveal: function () {
          if ($postsGrid) {
              $postsGrid.masonry("layout");
          }
      }
  });
});

没加载完的时候是一片空白。界面上什么都没有,造成一种假死的状态。

如果想加入 Disqus 评论个数的功能,需要引入 count.js,所以就导致了没翻墙的情况下,这个资源根本无法加载成功,阻塞了 $(window).load()

即时这个 script 标签设置 async=true,也是会阻塞。

解决办法很巧妙,既然 $(window).load() 只会在所有资源加载完毕的时候触发,那太简单了,把 Disqus 干掉不就好了么。。当然不行,干掉了还怎么显示评论个数。

JS 对资源的判定标准是,Tag 里面有 src Attribute,我们只需要把这个 Attribute 干掉,就能保证 $(window).load() 忽略掉这个 JS。

<script type="text/javascript">
    (function () {
        var s = document.createElement('script'); s.async = true;
        s.type = 'text/javascript';
        s.setAttribute('external_src', '//' + window.disqus_shortname + '.disqus.com/count.js');
        (document.getElementsByTagName('HEAD')[0] || document.getElementsByTagName('BODY')[0]).appendChild(s);
    }());
</script>

我们把 count.js 的 Attribute 设置为 external_src,就不会再阻塞 rendering,但是资源也没法加载了咋弄,这就更容易了,在 load 之后遍历一下:

$(window).load(function() {
    $('[external_src]').each(function() {
        var external_src = $(this).attr("external_src");
        $(this).attr("src", $(this).attr("external_src")).removeAttr("external_src");
    });
});

这样就完美解决了。

Tags

Jie Li

🚘 On-road / 📉 US Stock / 💻 Full Stack Engineer / ®️ ENTJ