Hexo 网站性能优化记录lqip

Hexo 网站性能优化记录

Intro

去年九月在博客性能优化文中,记录优化Hexo Blog性能措施。最近针对当时未解决的部分性能问题,又进行了一系列的优化,记录下来作为前文的补充

问题范畴​描述​
CDN​CloudFlare CDN​在国内体验不佳
字体资源​部分字体转成WOFF2格式后,体积仍超过10MB
图片资源​未使用响应式图片(无法根据设备分辨率传输适配尺寸的图片)
图片不支持渐进式加载
WebP 格式可进一步替换为更优的 AVIF 格式
HTML/JS/CSS​部分静态资源未做压缩处理​
冗余CSS规则​Hexo Icarus 主题依赖 Bulma CSS 框架,其中大量 CSS 代码未被实际调用,需针对性检测并删减。​
第三方JavaScript ​博客依赖的第三方 JavaScript 资源(如通过 jsDeliver、gstatic 等 CDN 加载的文件),在国内网络环境下体验不佳​

😄 效果还不错,下午测出一轮 Performance=99 的分数

perf_score_99

​优化工具

主要使用Chrome DevTools的部分功能:

  • Network Pannel:分析网络请求,查看请求耗时
  • Coverage:定位未被调用的CSS规则&JavaScirpt代码
  • LightHouse: 生成性能评分报告,并提供针对性优化建议

具体优化方案

CDN 相关优化

之前的文章 中,个人使用DNS Pod实现CDN的分线路解析,实现国内请求走缤纷云,境外走EdgeOne全球加速 (不包含大陆)。以此优化国内用户的访问响应速度。具体线路配置如下:

线路CDN回源站
境内缤纷云Edgeone Page
(大陆加速区)
境外EdgeOne CDN
(全球加速,不包含大陆)
CloudFlare Page

但部分第三方的资源(例如mathjax, medium-zoom etc.)请求是走的jsDelivery的CDN,在国内速度不佳。如果能找到合适的国内CDN源,也可以直接换。

但博客依赖的第三方资源(如 mathjax、medium-zoom 等)仍通过 jsDelivr 加载,国内访问速度不佳。如果能找到合适的国内 CDN 源,可直接替换;考虑到个人使用的第三方资源数量较少,于是选择将这些资源直接打包到构建产物中,对于Icarus来说,可参考个人提交的修改[1]来实现。后续资源请求即可统一走个人配置的缤纷云 CDN。

这块提升还是比较明显的,国内网络环境下的 curl 测速对比结果如下:

SHELL
cURL测速对比
开始测试 jsDelivr CDN (https://cdn.jsdelivr.net/npm/pjax@0.2.8/pjax.min.js)------------------------------------------------测试 1: 连接=0.209s, 开始传输=0.830s, 总时间=0.849s测试 2: 连接=0.209s, 开始传输=0.828s, 总时间=0.836s测试 3: 连接=1.197s, 开始传输=1.610s, 总时间=2.597s测试 4: 连接=0.196s, 开始传输=0.607s, 总时间=1.553s测试 5: 连接=0.197s, 开始传输=0.659s, 总时间=0.907s------------------------------------------------jsDelivr CDN 平均值:平均连接时间: 0.401s平均开始传输时间: 0.906s平均总时间: 1.348s------------------------------------------------开始测试 vluv.space (https://vluv.space/js/host/pjax/0.2.8/pjax.min.js)------------------------------------------------测试 1: 连接=0.100s, 开始传输=0.152s, 总时间=0.155s测试 2: 连接=0.025s, 开始传输=0.096s, 总时间=0.097s测试 3: 连接=0.026s, 开始传输=0.088s, 总时间=0.088s测试 4: 连接=0.028s, 开始传输=0.079s, 总时间=0.080s测试 5: 连接=0.030s, 开始传输=0.095s, 总时间=0.096s------------------------------------------------vluv.space 平均值:平均连接时间: 0.041s平均开始传输时间: 0.102s平均总时间: 0.103s------------------------------------------------

字体资源优化

如果在CSS中使用了非内置字体,那么可以考虑字体传输的优化问题。

一方面是使用高效的存储格式 (woff2)。此外,中文字体体积普遍较大,很多页面用不到全部字符,于是可以对字体进行切片。具体来说,在 @font-face 使用unicode-range[2]引用字体切片,浏览器会分析当前页面文字的范围,选择需要的字体切片文件下载,减少冗余传输

制作切片可能比较繁琐,多数情况下直接引用Google Font的链接即可(可能影响国内体验)。对于中文字体,则可以使用 ZeoSeven Fonts (ZSFT)字图 CDN | 中文网字计划提供的公益服务。例如个人是这样引用Maple Mono NF CN作为代码字体的

HTML
<link  rel='stylesheet'  href="https://fontsapi.zeoseven.com/442/main/result.css"  media="print"  onLoad="this.media='all'"/>

Minify HTML/JS/CSS

此前优化博客性能时,我曾尝试通过 Gulp 脚本实现资源压缩,但使用后发现该方案会导致 CSS 样式异常,最终弃用了。

最近发现 chenzhutian/hexo-all-minifier 插件可以一站式解决压缩问题,它集成了以下子插件,可以压缩HTML,JS,CSS, 本地Image。

插件开箱即用,下载好后在 _config.yml 中启用插件即可

YML
_config.yml
all_minifier: true

个人习惯将压缩静态文件的操作放在CI/CD Pipeline里执行,对于该插件,本地可以将 NODE_ENV 环境变量设置为 development 以略过压缩

Image Delivery

图片和视频是网页中的核心元素,通常是体积最大的资源。合理的图片和视频传输优化可以显著提升用户体验

选择更优的文件格式:AVIF & WebP

格式上的优化是很容易做的,推荐使用的格式包括Webp和AVIF[3],可以在 Can I use… 网站上查看各浏览器是否支持该格式,除了QQ浏览器和IE,主流浏览器基本上都支持AVIF。

support_status_of_avif

使用PicList的用户,可以在 设置-图片预处理设置 中设置将图片转换成AVIF格式后再上传。对于已上传的图片,可以编写脚本,使用ffmpeg批处理转换

piclist-image-process

对于视频资源,也可以采用更先进的编码格式来压缩体积。例如使用AV1,HEVC,VP9等编码格式,使用WebM等容器格式。

提供响应式图片

假设图片分辨率是4K,但用户屏幕分辨率是1K。即使给用户发了原图,实际上也并没有作用,徒增功耗

提供响应式图片[4]可以较好的优化这一点,浏览器可根据情况(屏幕分辨率,窗口大小,Device Pixel Ratio etc.),请求合适的资源,避免非必要的网络开销。

个人使用缤纷云S4 (S3 Compatible) 存储桶作为图床,Vibe Coding了一个Hexo插件,最终输出形如下面的 Image Element;

HTML
<div class="progressive_img_container"><img src="https://assets.vluv.space/20250705170546187.webp" srcset="https://assets.vluv.space/20250705170546187.webp?w=200 200w, https://assets.vluv.space/20250705170546187.webp?w=400 400w, https://assets.vluv.space/20250705170546187.webp?w=600 600w, https://assets.vluv.space/20250705170546187.webp?w=800 800w, https://assets.vluv.space/20250705170546187.webp?w=1200 1200w, https://assets.vluv.space/20250705170546187.webp?w=2000 2000w, https://assets.vluv.space/20250705170546187.webp?w=3000 3000w" loading="lazy" decoding="async" onload="this.classList.add('loaded')" srcset="https://assets.vluv.space/20250705170546187.webp?w=200 200w,     https://assets.vluv.space/20250705170546187.webp?w=400 400w,     https://assets.vluv.space/20250705170546187.webp?w=600 600w,     https://assets.vluv.space/20250705170546187.webp?w=800 800w,     https://assets.vluv.space/20250705170546187.webp?w=1200 1200w,     https://assets.vluv.space/20250705170546187.webp?w=2000 2000w,     https://assets.vluv.space/20250705170546187.webp?w=3000 3000w"    alt="20250705170546187"    class="medium-zoom-image loaded"><img class="thumbhash-placeholder" src="data:image/png;base64,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"></div>

如果使用的图床没有媒体处理能力,可以考虑使用 sharp 库,Vibe Coding一个js脚本来实现。

图片渐进式加载

图片渐进式加载方案比较多,原理是先加载低清晰度的占位图,待原图加载完成后再替换占位图,避免页面加载过程中出现空白区域。个人博客是基于thumbhash[5]实现的,效果如下,代码可参考 Efterklang/Bitiful_Responsive_And_Progressive_Image

Coverage

  • 使用Chrome DevTools的Coverage功能,定位并删除冗余的CSS/JavaScript;
  • 使用CSS Overview功能,分析CSS的使用情况,定位Non-simple selectors

如图,Coverage可以标记未使用的CSS/JavaScript,可以辅助我们定位冗余的代码。注意多测试几个页面,避免误删。

coverage_unused_css

对于Hexo Icarus主题,精简前后的css体积对比如下,代码可以参考个人仓库 hexo-theme-icarus/include/style/bulma at main · Efterklang/hexo-theme-icarus

SHELL
 default.css                   260.8 KB  █████████████████████████▓ clean_bulma.css               150.6 KB  ██████████████▓ clean_bulma+clean_css压缩.css 124.5 KB  ███████████▓

去掉未使用的CSS Rules后,浏览器解析CSS的时间也会减少。有能力的可以再拆分CSS文件,根据页面按需导入;同时换掉低效的CSS选择器,可以进一步提升页面性能

JavaScript延迟加载

可以使用 defer/async 属性标记JavaScript脚本,防止下载脚本过程阻塞DOM解析。两者在执行script的期间有所差异,参考下图

<script>Scripting:HTML Parser:<script defer>Scripting:HTML Parser:<script async>Scripting:HTML Parser:<script type=“module”>Scripting:HTML Parser:<script type=“module” async>Scripting:HTML Parser:parserfetchexecutionruntime →

对于Blog来说,统计访客的 busuanz.js 就推荐添加 defer 属性

HTML
<script defer src="/js/busuanzi.js"></script>

  1. feat(cdn): cdn now support host · Efterklang/hexo-theme-icarus@f508116 ↩︎

  2. unicode-range - CSS | MDN ↩︎

  3. AVIF(AV1 Image File) 格式由Alliance for Open Media(开放媒体联盟)于2019年推出 ↩︎

  4. 相关概念可参考响应式图片介绍,实现步骤参考 Server Responsive Image ↩︎

  5. ThumbHash: A very compact representation of an image placeholder ↩︎

Hexo 网站性能优化记录

https://vluv.space/Hexo_Perf_Optmize/

Author

GnixAij

Posted on

2025-10-12

Updated on

2025-12-16

License under