Posts Jekyll 网站性能优化
Post
Cancel

Jekyll 网站性能优化

近来,突然觉博客项目的 CSS 内容越来越多,多次在 HTML 与 CSS 之间增减内容,就会增加残留无效 CSS 内容的概率。经过查找资料,发现 Chrome 的 DevTools 自带的Coverage功能可以很好的解决这个问题。好奇心驱使下,自然想着寻找更多玩法,能不能借助 DevTools 提高网站性能呢?答案是肯定的。Lighthouse是 Chrome 的性能审查扩展程序,位置在 DevTools 的Audits选项栏。根据自动化审查结果,可以知道网站性能短板所在,再由报告提供的建议去优化缺陷。

Lighthouse 审查

devtool-audits

Audits有五项审查内容,分别是Performance, Progressive Web App, Best parctices, Accessibility, SEO等,可以根据自己的需要选择。本文针对其中的Performance(性能)。Chrome 打开目标网页,启动Audits,十几秒内即可完成审查。 网站的性能优化大概有以下几个方向:

  • JS 异步加载
  • 按业务分拆 JS/CSS 的调用
  • HTML 消除内嵌样式
  • 压缩 JS,CSS,HTML

下面将逐项叙述每个优化过程细节。

JS 异步加载

当浏览器扫描项目时,JS 代码便会阻止构建 DOM。对页面样式展示非必要的 JS 代码,可以使用异步调用,在<script>内部添加async标记。例如:

1
<script src="/assets/js/common.js" async></script>

分场景调用 JS/CSS

在 Jekyll 中,{% include %}的应用可以增加代码的简洁性,也可能造成页面的 JS/CSS 冗余。一般 Jekyll 项目的习惯是,项目所有的 JS/CSS 都在_includes/head.html中引入,然后通过{% include head.html %}导入每个下层 layout。很多时候,部分 JS/CSS 并不是每个页面都必须的。

例如,本站的post布局需要bootstrap-toc.js,此外的page布局,home布局都不需要 toc 相关的 JS/CSS。 这时应该把bootstrap-toc相关的 JS/CSS 单独放置到post布局上引用,从而增加了其他布局的加载及渲染速度。

HTML 去除内嵌样式

HTML 元素内部的style会降低渲染效率,如:

1
<span style="background: #fff; color: gray;">Some codes</span>

应定义一个class去替代:

1
2
3
4
5
<style>
. mystyle { background: #fff; color: gray; }
</style>

<span class="mystyle">Some codes</span>

CSS 压缩

使用 Jekyll 提供的 sass pipeline 压缩,每次编译的时候会自动压缩引入的 scss 文件,十分便捷。使用方法是,在项目_config.yml文件添加 sass 配置:

1
2
3
sass:
  sass_dir: /assets/css # Override jekyll default path '/_sass'
  style:  compressed

其中sass_dir为项目 CSS 目录。

将自己编写的 CSS 3 文件后缀修改为.scss,在 CSS 文件目录/assets/css下新建一个文件,命名为styles.scss,添加导入所需的 scss。例如,导入styles.scss同目录下的main.scsssyntax.scss两个文件,则styles.scss添加内容:

1
2
3
4
5
---
---

@import "main";
@import "syntax";

项目<head>引用作相应修改,去掉原先对每个独立 CSS 文件的<link rel="stylesheet">引用,改为对styles.css的引用:

1
<link rel="stylesheet" href="/assets/css/styles.css">

引用文件后缀使用了.css,这是因为.scss编译后后缀会被自动改为.css

JS 压缩优化

项目中自己编写的 JS 以及第三方的 JS 文件(未压缩),可使用 YUI Compressor 压缩,压缩结果命名可以在.js后缀前添加min标识。如原文件tools.js压缩后命名为tools.min.js

1
$ java -jar yuicompressor.jar tools.js -o tools.min.js

接着使用 Jekyll 的 Assest 特征合并引用所需的 JS,在 JS 目录下新建文件common.js,使用{% include %}引入其他 JS,如本站内容为:

1
2
3
4
5
6
7
---
---

{% include_relative dist/back-to-top.min.js %}
{% include_relative dist/category-collapse.min.js %}
{% include_relative dist/search-display.min.js %}
{% include_relative dist/sidebar-toggle.min.js %}

项目 HTML 的head中使用合并文件替代分开的几个文件引用:

1
<script src="/assets/js/common.js" async></script>

HTML 压缩

对于 Jekyll,有一个 Liquid 实现的开源方案提供解决:Jekyll-HTML-Compressor

安装很简单,首先到 Release 下载最新版的compress.html,拷贝到项目的_layouts目录下。然后修改最顶级的默认样式 _layouts/default.html,在它的头部添加 Yaml:

1
2
3
---
layout: compress
---

然后,在_config.yml添加配置:

1
2
3
4
5
6
7
8
compress_html:
  clippings: all
  comments: ["<!-- ", " -->"]
  endings: [html, head, body, li, dt, dd, rt, rp, optgroup, option, colgroup, caption, thead, tbody, tfoot, tr, td, th]
  profile: false
  blanklines: false
  ignore:
    envs: []

具体每个参数的含义可以参考项目 README 介绍,经过几步即完成了插件的安装。该注意的是,如果 post 使用了 Jekyll 的linenos,则需要额外解决内嵌<pre>压缩错乱的 BUG

具体表现为, 原始状态使用{% highlight LANGUAGE linenos %}时,生成的代码格式为:

1
2
3
4
5
6
7
<figure class="highlight">
  <pre>
    <code class="..." data-lang="...">
    Code snippet
    </code>
  </pre>
</figure>

当压缩HTML时,会把最外层的<pre></pre>删除,但是不完整,残留/>

1
2
3
4
5
6
<figure class="highlight">
  />
    <code class="..." data-lang="...">
    Code snippet
    </code>
</figure>

虽然这会造成样式大错乱,但是项目维护者不打算修改这个 bug,认为这样会增加扫描层数,大大增加项目 build 的时间。上述 issues#71 中,已经有用户提供了解决方法: 在_includes/中新建文件fixlinenos.html,添加内容:

1
2
3
4
{% if _code contains '<pre class="lineno">' %}
  {% assign _code = _code | replace: "<pre><code", "<code" %}
  {% assign _code = _code | replace: "</code></pre>", "</code>" %}
{% endif %}

在每篇 post 源码中,调用{% highlight LANGUAGE linenos %}的地方作出修改。

原始代码:

1
2
3
{% highlight AnyLanguage linenos %}
  Some code
{% endhighlight %}

应修改为:

1
2
3
4
5
{% capture _code %}
{% highlight AnyLanguage linenos %}
  Some code
{% endhighlight %}
{% endcapture %}{% include fixlinenos.html %}{{ _code }}

这样压缩就不会出现问题了,可是要注意的是,<pre>fixlinenos.html清除后,代码段的overflow: auto也会消失,需要为figure.highlight添加样式overflow: auto对超出父容器宽度的代码作水平滑动。

JSON 压缩

这个是个意外发现,和上一步 HTML 压缩 一样,文件头部加 YAML 声明调用压缩的layout即可:

1
2
3
---
layout: compress
---

服务器 GZIP 压缩

传输过程可以开启 Web 服务器的GZIP选项,如果博客是部署在 GitHub Pages 或 Coding Pages ,则默认开启了 GZIP 压缩传输。若是自己个人部署的 Web 服务器,如 Nginx,Apache 等,则需要跟进此点优化。

结语

上述只是针对本站的优化,并没有覆盖常规网站的所有优化点,更加全面细致的性能建议,可参考 Google 开发者文档

OLDER POST NEWER POST

Comments powered by Disqus.

Search Results