Hexo 博客性能优化指南

Hexo 博客性能优化指南

Hexo 是一个快速、简洁且强大的静态博客框架,但随着博客内容的增加,性能问题可能会逐渐显现。根据 Google 的研究,网页加载时间超过 3 秒时,用户很可能会离开网页。因此,尽可能减少网页加载时间、提高用户体验显得尤为重要。

本文将结合实际案例,分享一些优化 Hexo 博客性能的技巧,帮助你提升博客的加载速度和用户体验。


一、图片优化

1. 压缩图片

使用工具(如 TinyPNGImageOptim)压缩图片,减少图片大小。

2. 使用 WebP 格式

强烈建议使用 WebP 格式的图片,其体积更小、加载速度更快。根据 Can I Use 数据,WebP 格式在现代浏览器中有良好支持。

如果需要使用 PNG 格式图片,建议使用 TinyPNG 压缩图片,体积可减少 50% 以上。

3. 延迟加载

启用图片懒加载功能,仅在用户滚动到图片时加载,减少初始页面加载时间。可以使用 lazysizeslozad.js 等库实现。

4. 善用 srcset

srcset 属性可以根据设备分辨率选择合适的图片。将其用于封面大图,并配合 fetchpriority="high",可提高移动端加载速度:

1
2
3
4
5
6
7
8
9
10
<% if (theme.banner_srcset.enable) { %>
<picture>
<% for (var i of theme.banner_srcset.srcset) { %>
<source media="<%= i.media %>" srcset="<%- url_for(i.src, {relative: false}) %>">
<% } %>
<img fetchpriority="high" src="<%- url_for(theme.banner, {relative: false}) %>" alt="<%= post.title %>">
</picture>
<% } else { %>
<img fetchpriority="high" src="<%- url_for(theme.banner, {relative: false}) %>" alt="<%= post.title %>">
<% } %>

CSS/JS 优化

替换过时依赖

许多博客使用 fancybox 实现图片放大功能,但由于协议问题(高版本不再使用 MIT 协议),只能使用 fancybox v3 版本。然而,该版本已过时且不再维护,并且依赖庞大的 jQuery 库。为此,可以考虑使用 PhotoSwipe 替代 fancybox。相比之下,PhotoSwipe 更加轻量,体积从 31.8KB(jQuery) + 22.7KB(fancybox) + 3.5KB(css) 减少到 4.9KB(PhotoSwipe-lightbox) + 16.8KB(PhotoSwipe,懒加载) + 2.7KB(css)

延迟加载无关资源

虽然 reimu 提供了如 mermaid 等强大功能,但并非所有文章都需要这些功能。例如,在首页仅需加载文章标题、摘要和封面图,而无需加载 katexmermaid。因此,可以将 mermaid 的加载延迟到文章页,从而减少首页加载时间。

在文章页模板中,可以通过判断是否需要加载 mermaid,来按需加载资源:

1
2
3
4
html
<% if (theme.mermaid.enable && page.mermaid) { %>
<%- js({src: vendorCdn(theme.vendor.js.mermaid)[0], 'data-pjax': true}) %>
<% } %>

异步加载低优先级资源

资源也有高优和低优之分。像是字体、图标、进度条等资源属于高优资源,其应该尽快加载;而像是评论、统计、搜索等功能所对应的资源属于低优资源,其可以延迟加载。

对于 css,可以使用 rel="preload" 属性,使其异步加载,防止阻塞渲染:

1
<link rel="preload" href="" as="style" onload="this.onload=null;this.rel='stylesheet'">

对于 js,可以使用 asyncdefer 属性,使其异步加载,防止阻塞渲染:

1
2
<script src="" async></script>
<script src="" defer></script>

字体/图标优化

iconfont VS fontawesome

fontawesome 提供了非常丰富的图标,但是其体积也非常庞大。假如我们只需要其中的几个图标,但其分布在 fontawesome 的 brand、solid、regular 等多个字体文件中,这样就会导致我们不得不加载整个 fontawesome。而 iconfont 则可以根据我们的需求,选择性地下载我们需要的图标,从而减少字体文件的体积。

以 reimu 为例,v0.1 版本中使用的是 fontawesome,需要加载 regular.min.csssolid.min.cssbrands.min.css 这 3 个 css 文件以及对应的 woff2 字体文件。而在 v0.3 版本中,使用的是 iconfont,只需要加载 iconfont.cssiconfont.woff2 这 2 个文件,请求次数和体积都大大减少。

Font css 优化

字体文件的加载也是一个很重要的问题。字体文件的加载会阻塞渲染,因此我们需要尽快加载字体文件。但是,如果我们直接使用 @font-face 来加载字体文件,那么字体文件会在 css 加载完毕后才开始加载,这样就会导致字体文件的加载延迟。因此,我们可以使用 preconnectpreload 来提前加载字体文件:

1
2
<link rel="preconnect" href="https://fonts.gstatic.com/" crossorigin>
<link rel="preload" as="style" href="https://fonts.googleapis.com/css/xxxx">

对于 css 中使用的 iconfont 字体文件,我们也可以对其进行预加载:

1
<link rel="preload" href="//at.alicdn.com/t/c/font_xxxx.woff2" as="font" type="font/woff2" crossorigin="anonymous">