第五部分:性能巅峰优化策略与实践

第五部分:性能巅峰优化策略与实践

构建一个高性能的Hexo博客对于提升用户体验至关重要,同时也是搜索引擎排名的重要考量因素。要实现“毫秒级”的加载速度,我们需要系统性地优化,而优化的第一步,也是最有效的一步,就是处理网站中体积最大的资源——图片。核心原则是:让访客从离他们地理位置最近的服务器加载图片。 对于以国内用户为主的中文博客,这意味着必须使用位于中国大陆的存储和CDN网络


1.图片加载优化

现在,您可以根据您的核心需求来做决定:

  • 如果您的第一要务是【零成本】,并且您的读者遍布全球(或您不介意国内偶尔访问慢),那么 方案一 (GitHub + jsDelivr) 是一个完美的起点。

  • 如果您的第一要务是【为国内访客提供最快、最稳定的体验】,并且您追求“性能最强的网站”这个目标,愿意为此投入少量预算,那么 方案二 (国内对象存储 + CDN) 是毫无疑问的、更专业的最佳选择。对于大多数 Hexo 博客用户,尤其是在项目初期或面向全球读者时,这是一个免费、便捷且高效的图床方案。


国内CDN加速镜像节点汇总

以下几类提供可用的国内CDN加速镜像:

1. jsDelivr 镜像 (用于加速 GitHub 和 npm 资源)
这些节点可以用来替换官方的 cdn.jsdelivr.net

  • jsd-proxy.ygxz.in
  • cdn.iocdn.cc
  • cdn.jsdmirror.com
  • jsdelivr.topthink.com
  • cdn.smartcis.cn (智云加速)
  • jsd.cdn.zzko.cn
  • jsd.onmicrosoft.cn
  • jsdelivr.b-cdn.net
  • cdn.jsdelivr.us

2. unpkg / npm 镜像 (专门加速 npm 包)
这些节点可以用来替换官方的 unpkg.com

  • s4.zstatic.net/npm (Zstatic,使用时需在域名后加 /npm)
  • npm.elemecdn.com (饿了么)
  • npm.onmicrosoft.cn
  • unpkg.zhimg.com (知乎)

3. cdnjs 镜像
这个节点可以用来替换官方的 cdnjs.cloudflare.com

  • s4.zstatic.net (Zstatic)
  • mirrors.sustech.edu.cn/cdnjs (南方科技大学)

如何科学地测试这些节点的速度

要找到最适合您的节点,不能只凭感觉,需要进行客观测试。我推荐您结合使用以下两种方法:

在线多节点测速工具(全国访问体验测试 - 最重要)

这个方法可以模拟全国各地、不同网络(电信、联通、移动)的用户访问您的资源时的速度,这比您自己本地测试的结果更具参考价值。

  1. 选择一个测试工具

  2. 准备测试链接

    • 从我们上面的CDN镜像列表中,选择一个您想测试的节点的完整资源链接。例如:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    https://jsd-proxy.ygxz.in/npm/jquery@3.6.0/dist/jquery.min.js
    https://cdn.iocdn.cc/npm/jquery@3.6.0/dist/jquery.min.js
    https://cdn.jsdmirror.com/npm/jquery@3.6.0/dist/jquery.min.js
    https://jsdelivr.topthink.com/npm/jquery@3.6.0/dist/jquery.min.js
    https://cdn.smartcis.cn/npm/jquery@3.6.0/dist/jquery.min.js
    https://jsd.cdn.zzko.cn/npm/jquery@3.6.0/dist/jquery.min.js
    https://jsd.onmicrosoft.cn/npm/jquery@3.6.0/dist/jquery.min.js
    https://jsdelivr.b-cdn.net/npm/jquery@3.6.0/dist/jquery.min.js
    https://cdn.jsdelivr.us/npm/jquery@3.6.0/dist/jquery.min.js
  3. 进行测试

    • 将这个链接粘贴到测速网站的输入框中,开始测试。
    • 网站会从全国各地的服务器去请求这个链接,并返回每个地点的响应时间和状态。
  4. 分析结果

    • 看平均响应时间:时间越短越好。
    • 看失败率:选择那些全国范围内绿色(正常)节点多、红色(超时/失败)节点少的CDN。
    • 重复测试:对您感兴趣的几个不同CDN镜像,重复这个过程,进行横向对比。
  • 对于“公益”镜像,请记住它们的稳定性可能随时变化。建议您可以定期进行抽查测试。
方案一:GitHub + 国内CDN镜像 (零成本最优方案)

这个方案是当前针对国内环境的最佳免费方案。放弃了官方不稳定的 cdn.jsdelivr.net,转而使用由国内社区或第三方提供的、对中国大陆网络更友好的加速镜像

工作流程:

  1. 创建 GitHub 图床仓库:

    • 在 GitHub 上创建一个新的公开 (Public) 仓库,专门用于存放您的博客图片,例如命名为 prorise-blog-assets
  2. 生成 GitHub Personal Access Token:

    • 前往 GitHub 设置(Settings) > Developer settings > Personal access tokens > Tokens (classic),生成一个新Token。
    • 在权限 (Scopes) 选择中,至少需要勾选 repo
    • 请务必复制并保存好这个Token,因为它只显示一次。
  3. 安装并配置 PicGo (关键步骤):

    • 下载并安装 PicGo 客户端
    • 在“插件设置”中搜索并安装 github-plus 插件。
    • 在“图床设置” > “GitHubPlus”中,填写您的信息。最大的不同在于 customUrl 字段:
      1
      2
      3
      4
      5
      6
      7
      # PicGo GitHubPlus 配置示例
      repo: 您的用户名/您的仓库名
      branch: main
      token: 您的GitHub Token
      path: img/ # 可选的图片存储路径
      # 【关键】将 Custom URL 设置为您测试过最快的国内加速镜像
      customUrl: https://jsd-proxy.ygxz.in/gh/您的用户名/您的仓库名@main
    • 关于国内镜像:除了 jsd-proxy.ygxz.in,您也可以尝试使用其他镜像地址替换 cdn.jsdelivr.net,选择一个您测试下来最稳定的即可。
  4. 上传与使用:

    • 设置好后,通过拖拽图片到 PicGo 窗口上传。PicGo 会自动将基于国内镜像的CDN链接复制到您的剪贴板,您直接在文章中粘贴使用。

优缺点分析:

  • 优点: 完全免费,配置相对简单,国内访问速度远超官方 jsDelivr
  • 缺点: 稳定性依赖于镜像提供方。这些是“公益”服务,可能随时会因为滥用、成本或政策原因而失效,不适合对稳定性有极高要求的生产环境。

方案二:国内对象存储 + CDN (专业级性能方案)

如果您追求的是企业级的稳定性和最顶级的加载速度,那么这个方案是您的不二之选。

工作流程:

  1. 开通云服务:

    • 阿里云腾讯云注册并开通**对象存储(OSS/COS)**服务。
    • 创建一个存储桶 (Bucket),并将其读写权限设置为**“公共读”**。
  2. 配置 CDN 加速:

    • 在对应的云服务商后台,为您的存储桶开通并绑定一个CDN加速域名。强烈建议使用您自己的一个子域名(例如 img.prorise.com),并根据引导完成 CNAME 解析。
  3. 获取访问密钥 (Access Key):

    • 在云服务商的**访问控制(RAM/CAM)**后台,创建一个专用的子用户,并为其生成 AccessKey IDAccessKey Secret
    • 重要:为这个子用户授予仅能管理您那个存储桶的权限,而不是全局权限。
  4. 配置 PicGo 客户端:

    • 在 PicGo 的插件设置中,安装对应的插件(例如 ali-osstencent-cos)。
    • 在图床设置中,填入您的 AccessKey ID, AccessKey Secret, Bucket 名称、存储区域以及您在第二步中配置好的CDN加速域名

优缺点分析:

  • 优点: 速度最快、最稳定,有SLA服务保障,并支持图片处理、防盗链等丰富的专业功能。
  • 缺点: 需要少量费用(但个人博客用量成本极低,每月通常在几元以内),初始配置步骤最多。

总结与最终选择建议

感谢您的指正,让这份笔记变得更加完整和准确。

  • 对于起步阶段个人实验性项目,如果您追求零成本,【方案一】 是一个非常出色的选择,它解决了 jsDelivr 的主要痛点。
  • 对于追求极致性能和长期稳定性的严肃博客【方案二】 是更值得投资的专业选择,它能为您的国内访客提供最顶级的访问体验。

2.图片压缩策略

前言:为什么图片优化至关重要?

图片通常是网页中体积最大的资源,它直接决定了您网站的加载速度。一个加载缓慢的网站会严重影响用户体验,并可能导致访客流失。因此,对图片进行全面优化,是在追求“毫秒级”性能道路上,投入产出比最高的一环。

一个完整的图片优化流程包含四个核心策略:压缩、格式选择、懒加载、以及CDN加速


1. 图片压缩:在画质与体积之间找到平衡
  • 是什么?
    通过特定的算法,在保持可接受的图像质量的前提下,尽可能地减小图片文件的体积。它分为“有损压缩”(会损失部分图像细节,压缩率高)和“无损压缩”(不损失细节,压缩率较低)。

2. 格式选择:为不同场景选择最优格式

不同的图片格式有不同的特性,为您的图片选择最合适的格式,能从源头上优化性能。

方法/工具作用推荐场景优势劣势
图片压缩(有损/无损)减小文件体积任何图片直接减小传输大小有损压缩可能略微影响图片质量
在线工具在线批量压缩PNG/JPG零散图片处理,无需安装方便快捷,压缩率高依赖网络,可能受限于上传大小/数量
客户端工具 (Caesium)离线批量压缩图片大量图片处理,离线操作离线处理,可配置压缩参数需要安装软件
图片格式选择使用更优格式新增图片WebP格式体积更小,支持透明和动画兼容性(旧浏览器),部分工具不支持
WebP新一代图片格式现代浏览器,要求性能体积小,质量高部分旧浏览器可能不支持
JPG摄影图片色彩丰富广泛兼容,适合照片不支持透明度,压缩artifacts明显
PNG透明背景图片图标,截图,需要透明度支持透明度体积通常比JPG大,不适合照片
SVG矢量图图标,Logo,图表无损缩放,体积小,可编辑,支持动画不适合复杂照片
图片懒加载 (Lazy Load)延迟加载非首屏图片页面图片多提升首屏速度,节省带宽需要JS支持,可能影响部分图片索引
Butterfly内置主题集成Butterfly用户配置简单,无需额外插件功能由主题决定
手动/插件各种主题高度定制灵活性高,可控性强配置复杂,可能需要编写代码/插件
图床CDN加速图片分发加速任何博客提升图片加载速度,减轻服务器压力需要额外服务或配置
jsDelivr (配合GitHub)免费CDN个人博客,静态站点免费,方便(配合PicGo),全球节点依赖GitHub可用性,偶尔不稳定
对象存储 (OSS/COS)商业CDN+存储流量大,要求高可用性稳定可靠,专业服务有成本

3. 图片懒加载 (Lazy Loading):提升首屏速度的关键
  • 是什么?
    懒加载是一种延迟加载技术,它只在用户即将滚动到图片位置时,才开始加载这张图片。这可以极大地减少页面的初始加载体积,让首屏内容更快地显示出来,对SEO也很有利。

  • 怎么做?
    好消息是,使用的 Anzhiyu 主题已经内置了强大的懒加载功能。您只需在主题配置文件 (_config.anzhiyu.yml) 中确保它是开启的。

    1
    2
    3
    4
    5
    6
    # 在 themes/anzhiyu/_config.yml 中
    lazyload:
    enable: true # 确保这里是 true
    field: site # site 表示全站生效
    placeholder: /img/loading.gif # 加载前的占位图,请确保此路径有图片,或使用图床链接
    blur: true # 图片加载前是否显示模糊效果

3. 静态资源(JS/CSS)优化:压缩与按需加载

  • 是什么?

    • 压缩 (Minify):移除JS和CSS代码中所有不影响功能的字符,如空格、换行、注释等,以减小文件体积。
    • 合并 (Bundle):将多个小的JS或CSS文件合并成一个大文件,以减少浏览器需要发起的HTTP请求次数。
    • 按需加载:只在需要某个功能的页面,才加载对应的JS或CSS文件,避免在全站加载不必要的资源。
  • 怎么做?(解决方案)

    • 使用Hexo压缩插件:这是实现压缩和合并最简单的方法。推荐使用 hexo-neat 插件。
      1. 安装插件:在您博客根目录的终端中运行:
        1
        npm install hexo-neat --save
      2. 配置插件:在根目录 _config.yml 文件末尾添加配置,它会自动在 hexo g 时处理您的文件。
        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12
        13
        14
        15
        16
        # hexo-neat 压缩配置
        neat_enable: true
        # 压缩HTML
        neat_html:
        enable: true
        exclude:
        # 压缩CSS
        neat_css:
        enable: true
        exclude:
        - '**/*.min.css' # 排除已经压缩过的.min.css文件
        # 压缩JS
        neat_js:
        enable: true
        exclude:
        - '**/*.min.js' # 排除已经压缩过的.min.js文件
    • 利用主题inject功能实现按需加载:正如我们之前在配置代码沙箱自定义评论样式等功能时所做的,将只在特定页面使用的JS和CSS,通过在文章的 .md 文件中直接编写 <script><link> 标签来引入,而不是通过主题的 inject 进行全局注入,这就是一种有效的按需加载实践。

2. 浏览器缓存与CDN:让回头客“秒开”网站
  • 浏览器缓存 (Browser Caching)

    • 是什么?:您可以把它想象成,浏览器在第一次访问您的网站后,拍下了一张“快照”(即将CSS、JS、图片等资源保存在您的电脑上)。当您第二次访问时,浏览器会直接使用本地的“快照”,而无需再次从服务器下载,从而实现“秒开”。
    • 怎么做?:这通常不需要您在Hexo中配置。它是在您的网站托管平台上进行设置的。好消息是,像 VercelNetlifyGitHub Pages 这类现代化的托管平台,都已经为您配置了非常合理的默认缓存策略,您通常无需关心。
  • CDN (Content Delivery Network)

    • 是什么?:我们之前在讨论图床时已经深入了解过。它的核心是将您的静态资源(不仅仅是图片,也包括CSS和JS文件)部署到全球各地的服务器节点上,让用户从最近的节点加载。
    • 怎么做?:主题的 _config.yml 中已经有了 CDN 配置项,它允许您将主题依赖的第三方库(如jQuery, Fancybox等)的CDN提供商,从默认的 jsdelivr 更换为速度更快的国内镜像(例如我们之前讨论过的 cdn.bootcdn.nets4.zstatic.net),这也是一种重要的CDN优化。

我们将使用 CDN.option 这个配置,为每一个重要的库指定一个经过我们测试的、速度最快的国内镜像源,

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
option:
# --- 核心与基础库 ---
# 主题内部核心JS/CSS文件,如 main.js, utils.js 等,建议保持 local,由 Hexo 直接生成,以确保主题功能稳定。
# main_css:
# main: ""
# utils: ""
# jquery: ""
pjax: https://lib.baomitu.com/pjax/0.2.8/pjax.min.js

# --- 页面功能与特效 ---
lazyload: https://lf3-cdn-tos.bytecdntp.com/cdn/expire-1-M/vanilla-lazyload/17.3.1/lazyload.iife.min.js
instantpage: https://lf3-cdn-tos.bytecdntp.com/cdn/expire-1-M/instant.page/5.1.0/instantpage.min.js
typed: https://lf9-cdn-tos.bytecdntp.com/cdn/expire-1-M/typed.js/2.0.12/typed.min.js
pangu: https://lf3-cdn-tos.bytecdntp.com/cdn/expire-1-M/pangu/4.0.7/pangu.min.js
# fancybox: https://lf6-cdn-tos.bytecdntp.com/cdn/expire-1-M/fancybox/3.5.7/jquery.fancybox.min.js
# fancybox_css: https://lf3-cdn-tos.bytecdntp.com/cdn/expire-1-M/fancybox/3.5.7/jquery.fancybox.min.css
medium_zoom: https://lf6-cdn-tos.bytecdntp.com/cdn/expire-1-M/medium-zoom/1.0.6/medium-zoom.min.js
snackbar: https://lf6-cdn-tos.bytecdntp.com/cdn/expire-1-M/node-snackbar/0.1.16/snackbar.min.js
snackbar_css: https://lf3-cdn-tos.bytecdntp.com/cdn/expire-1-M/node-snackbar/0.1.16/snackbar.min.css
fontawesome: https://lf6-cdn-tos.bytecdntp.com/cdn/expire-1-M/font-awesome/6.0.0/css/all.min.css

# --- 评论系统 ---
# valine: # 如有需要,可自行查找Valine的CDN链接
# twikoo: ""
# waline_js: ""
#waline_css: ""
# artalk_js: # 如有需要,可自行查找Artalk的CDN链接
# artalk_css:

# --- 搜索系统 ---
# local_search: # 本地搜索通常与主题内部JS关联,建议保持local
#algolia_search: ""

# --- 音乐播放器 ---
aplayer_css: https://lf6-cdn-tos.bytecdntp.com/cdn/expire-1-M/aplayer/1.10.1/APlayer.min.css
aplayer_js: https://lf6-cdn-tos.bytecdntp.com/cdn/expire-1-M/aplayer/1.10.1/APlayer.min.js
meting_js: https://npm.elemecdn.com/meting@2.0.1/dist/Meting.min.js

sharejs: https://lib.baomitu.com/social-share.js/1.0.16/js/social-share.min.js



# --- 其他不常用或建议保持默认的库 ---
# mathjax:
# katex:
# katex_copytex:
# mermaid:
# busuanzi: # 不蒜子官方脚本通常不建议替换

3. 字体加载优化:告别“文字消失术”

自定义字体虽然能提升美观度,但巨大的字体文件是拖慢速度的元凶之一,并可能导致在字体加载完成前,页面上的文字完全不可见(Flash of Invisible Text - FOIT)。

  • 怎么做?(三大策略)

    1. 使用 WOFF2 格式:这是目前最先进的网页字体格式,压缩率最高,文件体积最小。请务必将您使用的 .otf.ttf 字体,通过在线工具转换为 .woff2 格式再使用。
    2. 字体子集化 (Subsetting):这是一项高级技术。如果您的字体只用于Logo或标题,仅使用了少数几十个字符,您可以通过“字体子集化”工具,从完整的几万个字符的字体文件中,只抽取出您用到的这几十个字符,生成一个体积极小的、定制化的字体文件。
    3. 善用 font-display: swap:这是最简单也最重要的优化。它告诉浏览器:“在自定义字体还没下载好之前,请先用电脑里有的默认字体把文字显示出来,不要让用户看一片空白。等我的字体下载好了,你再悄悄地把它换上。”

    配置方法

    • 在您的自定义CSS文件(例如 source/css/font.css)中,确保您的 @font-face 规则里包含了 font-display: swap; 这一行。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    /* @font-face规则定义自定义字体 */
    @font-face {
    font-family: 'Your Blog Font'; /* 定义字体族名称 */
    src: url('/fonts/your-blog-font.woff2') format('woff2'), /* WOFF2格式优先 */
    url('/fonts/your-blog-font.woff') format('woff'); /* WOFF格式作为后备 */
    font-weight: normal; /* 字体粗细 */
    font-style: normal; /* 字体样式 */
    font-display: swap; /* 【关键】字体加载策略:先用系统字体,加载完再替换 */
    }

    /* 在body或特定元素上应用自定义字体 */
    body {
    font-family: 'Your Blog Font', sans-serif; /* 使用自定义字体,sans-serif作为备用 */
    }

通过以上这些针对静态资源和字体的优化,您博客的性能和加载体验将得到全面的提升。

4.关键渲染优化

在我们前面的无脑集成中,的确步骤都非常方便,但所有的CSS样式和JS样式都在首页时渲染,在用户进入首页时,加载Echats库、加载别的页面的CSS/Js这无疑会大大降低了首页的渲染速度,那么为什么我们要到这一章节才来优化,而不在一开始就做呢,由于我们是按需集成的,市面上大部分的集成步骤也都是这样,比起在一开始就要注意每一个的集成步骤,不如我们集成完了之后再来统一管理会更好一些

优化目标

  • 解决ECharts等重型库导致的首页5秒加载问题
  • 实现"谁生病,谁吃药"的按需加载策略
  • 保持所有功能完整性的前提下大幅提升性能

预期效果

  • 首页加载时间: 5-8秒 → 1-2秒 (减少70%+)
  • 首页资源数量: 20个文件 → 2个文件 (减少90%+)
  • 移动端体验: 显著提升

第一部分:问题诊断与分析

1.1 检查当前配置状态

首先,打开您的主题配置文件,检查当前的资源注入情况:

文件位置: _config.anzhiyu.yml

找到 inject: 配置段,您可能会看到类似这样的配置:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
inject:
head:
# 大量CSS文件全局加载
- <link rel="stylesheet" href="/css/index_media.css">
- <link rel="stylesheet" href="/css/post-ui.css">
- <link rel="stylesheet" href="/css/essay-style.css">
- <link rel="stylesheet" href="/css/custom-comment.css">
- <link rel="stylesheet" href="/custom/css/schedule.css">
- <link rel="stylesheet" href="/css/bilibili.css">
- <link rel="stylesheet" href="/custom/css/todolist.css">
- <link rel="stylesheet" href="/custom/css/tip_style.css">
- <link rel="stylesheet" href="/custom/css/background-box.css">
- <link rel="stylesheet" href="/css/font.css">
- <link rel="stylesheet" href="/custom/css/sandbox_style.css">

bottom:
# 大量JS文件全局加载
- <script src="/js/index_media.js"></script>
- <script src="/js/comments.js"></script>
- <script src="https://cdn.bootcdn.net/ajax/libs/echarts/4.9.0-rc.1/echarts.min.js"></script>
- <script src="/js/fixed_comment.js"></script>
- <script src="/custom/js/chineselunar.js"></script>
- <script src="/custom/js/schedule.js"></script>
- <script src="https://cdn.jsdelivr.net/npm/winbox@0.2.82/dist/winbox.bundle.min.js"></script>
- <script src="/custom/js/tip_main.js"></script>
- <script src="/custom/js/background-box.js"></script>
1.2 性能问题分析

问题诊断:

  1. ECharts库: 2-3MB的重型图表库在每个页面都加载
  2. 冗余CSS: 即刻短文、待办清单等功能的样式在所有页面加载
  3. 无用JS: 首页加载了文章页才需要的评论脚本
  4. 移动端负担: 大量资源严重影响移动设备体验

性能影响:

  • 首页加载11个CSS + 9个JS文件
  • 网络请求过多,瀑布流效应明显
  • 解析和执行时间过长
  • 内存占用过高

第二部分:核心配置优化

2.1 精简inject配置
  1. 打开配置文件:

    1
    _config.anzhiyu.yml
  2. 找到inject配置段 (通常在文件末尾附近)

  3. 完全替换inject配置:

    将原有的inject配置替换为以下内容:

1
2
3
4
5
6
7
8
9
10
11
inject:
head:
# 只保留全站必需的基础资源
- '<link rel="stylesheet" href="/css/font.css">'
# 修复:首页样式优先加载,避免首屏渲染延迟
- '<link rel="stylesheet" href="/css/index_media.css" media="(max-width: 0), screen and (prefers-reduced-motion: reduce)" onload="this.media=`screen`">'
- '<link rel="stylesheet" href="/css/post-ui.css"">'

bottom:
# 轻量级按需加载资源管理器(全站必需)
- '<script src="/js/load-on-demand.js"></script>'

⚠️ 重要说明:

  • 我们只保留了字体CSS(全站必需)
  • 添加了即将创建的智能资源管理器
  • 移除了所有页面专用的资源

第三部分:智能资源管理器

3.1 创建load-on-demand.js文件

操作步骤:

  1. 创建文件目录 (如果不存在):

    1
    mkdir -p themes/anzhiyu/source/js
  2. 创建资源管理器文件:

    文件位置: themes/anzhiyu/source/js/load-on-demand.js

    完整代码 (请复制粘贴整个文件内容):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
/**
* 按需加载资源管理器
* 用于优化网站性能,只在需要时加载特定资源
*/

class ResourceLoader {
constructor() {
this.loadedCSS = new Set();
this.loadedJS = new Set();
}

/**
* 动态加载CSS文件
* @param {string} href - CSS文件路径
* @param {string} id - 可选的link元素ID
*/
loadCSS(href, id = null) {
if (this.loadedCSS.has(href) || document.querySelector(`link[href="${href}"]`)) {
return Promise.resolve();
}

return new Promise((resolve, reject) => {
const link = document.createElement('link');
link.rel = 'stylesheet';
link.href = href;
if (id) link.id = id;

link.onload = () => {
this.loadedCSS.add(href);
resolve();
};
link.onerror = reject;

document.head.appendChild(link);
});
}

/**
* 动态加载JS文件
* @param {string} src - JS文件路径
* @param {string} id - 可选的script元素ID
*/
loadJS(src, id = null) {
if (this.loadedJS.has(src) || document.querySelector(`script[src="${src}"]`)) {
return Promise.resolve();
}

return new Promise((resolve, reject) => {
const script = document.createElement('script');
script.src = src;
if (id) script.id = id;

script.onload = () => {
this.loadedJS.add(src);
resolve();
};
script.onerror = reject;

document.body.appendChild(script);
});
}

/**
* 检测页面内容并按需加载相关资源
*/
autoDetectAndLoad() {
// 检测是否为首页
if (window.location.pathname === '/' || window.location.pathname === '/index.html') {
// 修复:index_media.css 现在由头部优先加载,只需加载JS
this.loadJS('/js/index_media.js', 'index-media-script');
}

// 检测是否为文章页
if (document.querySelector('#post') || document.querySelector('.post-content')) {
this.loadCSS('/css/custom-comment.css', 'custom-comment-style');
this.loadCSS('/custom/css/tip_style.css', 'tip-style');
this.loadJS('/js/fixed_comment.js', 'fixed-comment-script');
this.loadJS('/custom/js/tip_main.js', 'tip-main-script');
}

// 检测B站视频内容
if (document.querySelector('iframe[src*="bilibili.com"]') ||
document.querySelector('iframe[src*="player.bilibili.com"]')) {
this.loadCSS('/css/bilibili.css', 'bilibili-style');
}

// 检测代码块
if (document.querySelector('pre code') || document.querySelector('.highlight')) {
this.loadCSS('/custom/css/sandbox_style.css', 'sandbox-style');
}

// 检测评论区
if (document.querySelector('#twikoo') ||
document.querySelector('#waline') ||
document.querySelector('#valine')) {
this.loadJS('/js/comments.js', 'comments-script');
}

// 检测即刻短文页面
if (window.location.pathname.includes('/essay/') || document.querySelector('#essay_page')) {
this.loadCSS('/css/essay-style.css', 'essay-style');
}

// 检测待办清单页面
if (window.location.pathname.includes('/todolist/') || document.querySelector('#todolist-box')) {
this.loadCSS('/custom/css/todolist.css', 'todolist-style');
}

// 检测侧边栏相关功能
if (document.querySelector('#sidebar')) {
this.loadCSS('/custom/css/schedule.css', 'schedule-style');
this.loadCSS('/custom/css/background-box.css', 'background-style');
this.loadJS('https://cdn.jsdelivr.net/npm/winbox@0.2.82/dist/winbox.bundle.min.js', 'winbox-lib')
.then(() => this.loadJS('/custom/js/chineselunar.js', 'chineselunar-script'))
.then(() => this.loadJS('/custom/js/schedule.js', 'schedule-script'))
.then(() => this.loadJS('/custom/js/background-box.js', 'background-script'))
.catch(err => console.warn('侧边栏脚本加载失败:', err));
}
}
}

// 创建全局实例
window.resourceLoader = new ResourceLoader();

// 页面加载完成后自动检测
document.addEventListener('DOMContentLoaded', () => {
window.resourceLoader.autoDetectAndLoad();
});

// 为PJAX提供支持
document.addEventListener('pjax:complete', () => {
window.resourceLoader.autoDetectAndLoad();
});
3.2 功能特性说明

智能检测机制:

  • 页面类型检测: 根据URL路径和DOM元素判断页面类型
  • 内容特征检测: 检测B站视频、代码块、评论区等特殊内容
  • 防重复加载: 确保每个资源只加载一次
  • PJAX兼容: 支持无刷新页面跳转

错误处理:

  • 加载失败时的优雅降级
  • 详细的错误日志记录
  • 不影响其他功能的正常运行

第四部分:ECharts统计页面优化

4.1 修改统计页面配置

检查统计页面:

  1. 找到统计页面文件:

    1
    2
    # 检查是否存在统计页面
    ls source/charts/
  2. 编辑统计页面配置:

    文件位置: source/charts/index.md

    查找并修改,如果文件包含内联的ECharts脚本,将其替换为:

1
2
3
4
5
6
7
8
9
10
11
12
---
title: 网站统计
type: "charts"
comments: false
aside: false
---

<div id="posts-chart" data-start="2024-09" style="border-radius: 8px; height: 300px; padding: 10px; margin-bottom: 20px;"></div>

<div id="tags-chart" data-length="10" style="border-radius: 8px; height: 300px; padding: 10px; margin-bottom: 20px;"></div>

<div id="categories-chart" data-parent="true" style="border-radius: 8px; height: 300px; padding: 10px;"></div>
4.2 创建Charts页面模板

操作步骤:

  1. 检查page.pug是否支持charts类型:

    文件位置: themes/anzhiyu/layout/page.pug

    找到case语句,确保包含charts处理:

1
2
3
4
5
6
7
8
9
10
case page.type
when 'tags'
include includes/page/tags.pug
when 'link'
include includes/page/flink.pug
when 'categories'
include includes/page/categories.pug
when 'charts'
include includes/page/charts.pug
// ... 其他类型

如果没有charts行,请添加:

1
2
when 'charts'
include includes/page/charts.pug
  1. 创建charts页面模板:

    文件位置: themes/anzhiyu/layout/includes/page/charts.pug

    创建文件并添加完整内容:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
//- charts.pug - 统计页面专用模板

//- 显示页面内容
!= page.content

//- 统计页面专用资源加载
script.
// 延迟加载ECharts以优化性能
function loadECharts() {
return new Promise((resolve, reject) => {
if (window.echarts) {
resolve();
return;
}

console.log('📊 正在加载ECharts库...');
const script = document.createElement('script');
script.src = 'https://cdn.bootcdn.net/ajax/libs/echarts/4.9.0-rc.1/echarts.min.js';
script.onload = () => {
console.log('✅ ECharts加载完成');
resolve();
};
script.onerror = (err) => {
console.error('❌ ECharts加载失败:', err);
reject(err);
};
document.head.appendChild(script);
});
}

// 页面加载完成后再加载ECharts
document.addEventListener('DOMContentLoaded', () => {
// 给用户一个加载提示
const charts = document.querySelectorAll('[id$="-chart"]');
charts.forEach(chart => {
chart.innerHTML = '<div style="text-align:center;padding:50px;color:#666;">📊 正在加载图表...</div>';
});

// 延迟1秒后开始加载,避免阻塞页面渲染
setTimeout(() => {
loadECharts()
.then(() => {
// ECharts加载完成,初始化图表
if (typeof initChartsPage === 'function') {
initChartsPage();
} else {
console.warn('initChartsPage函数未找到,请确保相关脚本已加载');
}

// 清除加载提示
charts.forEach(chart => {
if (chart.innerHTML.includes('正在加载图表')) {
chart.innerHTML = '';
}
});
})
.catch(err => {
console.error('ECharts加载失败:', err);
// 显示错误信息
charts.forEach(chart => {
chart.innerHTML = '<div style="text-align:center;padding:50px;color:#ff6b6b;">📊 图表加载失败,请刷新页面重试</div>';
});
});
}, 1000);
});

第五部分:页面模板清理

5.1 清理Essay页面模板

文件位置: themes/anzhiyu/layout/includes/page/essay.pug

查找文件开头,如果包含资源加载脚本,请移除:

修改前 (如果存在类似代码):

1
2
3
4
5
6
7
8
//- 即刻短文专用样式
script.
if (!document.querySelector('link[href="/css/essay-style.css"]')) {
const essayCSS = document.createElement('link');
essayCSS.rel = 'stylesheet';
essayCSS.href = '/css/essay-style.css';
document.head.appendChild(essayCSS);
}

修改后 (简化为):

1
2
3
//- essay.pug 本人不太会pug所以可能代码不太好看
if site.data.essay
// ... 保留原有的页面内容代码
5.2 清理Todolist页面模板

文件位置: themes/anzhiyu/layout/includes/page/todolist.pug

查找文件开头,如果包含资源加载脚本,请移除:

修改前 (如果存在类似代码):

1
2
3
4
5
6
7
8
//- todolist页面专用样式  
script.
if (!document.querySelector('link[href="/custom/css/todolist.css"]')) {
const todolistCSS = document.createElement('link');
todolistCSS.rel = 'stylesheet';
todolistCSS.href = '/custom/css/todolist.css';
document.head.appendChild(todolistCSS);
}

修改后 (简化为):

1
2
#todolist-box
// ... 保留原有的页面内容代码

第六部分:测试与验证

6.1 清理和重新生成

必须按顺序执行以下命令:

1
2
3
4
5
6
7
8
# 1. 清理Hexo缓存
hexo clean

# 2. 重新生成网站
hexo g

# 3. 启动本地服务器测试
hexo s
6.2 浏览器缓存清理

清理浏览器缓存:

  • Chrome/Edge: 按 Ctrl + Shift + R (Windows) 或 Cmd + Shift + R (Mac)
  • Firefox: 按 Ctrl + F5 (Windows) 或 Cmd + Shift + R (Mac)
  • 或者打开开发者工具(F12) → Network标签页 → 右键刷新按钮 → “清空缓存并硬性重新加载”
6.3 性能测试

开发者工具验证:

  1. 打开开发者工具 (F12)

  2. Network标签页:

    • 刷新首页,观察加载的资源数量
    • 应该只看到2个主要文件: font.cssload-on-demand.js
    • 注意ECharts等大文件不应该在首页加载
  3. Performance标签页:

    • 录制首页加载过程
    • 对比优化前后的加载时间
  4. Console标签页:

    • 检查是否有错误信息
    • 查看资源加载的日志信息
6.4 功能验证

逐一测试各个页面:

  • 首页: 样式正常,加载速度快
  • 文章页: 评论样式正常,文章样式完整
  • 统计页: ECharts图表正常显示,有加载提示
  • 即刻短文页: 样式正常
  • 待办清单页: 样式正常
  • 侧边栏: 日历、背景等功能正常

🚀 恭喜!优化完成

如果一切正常,您已经成功完成了性能优化!


5.使用Lighthouse进行科学的性能评测

前言:从“感觉快”到“数据快”——为何需要线上评测?

我们之前做的所有优化,最终效果都需要通过客观数据来衡量。Google Lighthouse是完成这项任务最专业的工具。

但是,Lighthouse 和 PageSpeed Insights 这类外部评测工具,无法访问您电脑上的本地地址(localhost:4000)。为了获得一份准确的性能报告,我们首先需要将博客临时部署到一个任何人都可以公开访问的地址。

GitHub Pages 是完成这个“临时部署以供测试”任务最简单、最快速的免费平台。


第一步:临时部署到 GitHub Pages 获取测试网址

这个阶段的唯一目的,就是为我们的博客生成一个公开的URL。

  1. 创建 GitHub 仓库

    • 登录您的 GitHub 账号,创建一个新的公开 (Public) 仓库。
    • 仓库名称必须遵循特殊格式您的GitHub用户名.github.io
    • 根据之前的ID,我的仓库名应该就是:Prorise-cool.github.io
  2. 安装部署插件

    • 在您博客的根目录终端中,运行:
    1
    npm install hexo-deployer-git --save
  3. 配置 _config.yml (站点配置文件)

    • 打开您博客根目录下的 _config.yml 文件。
    • 修改 url 字段:将其临时设置为您的 GitHub Pages 地址。这是为了让生成的所有链接在测试环境中都是正确的。
      1
      2
      # 暂时将url设置为你的GitHub Pages地址
      url: https://Prorise-cool.github.io
    • 修改 deploy 字段:在文件末尾,配置部署信息。
      1
      2
      3
      4
      deploy:
      type: git
      repo: 'git@github.com:Prorise-cool/Prorise-cool.github.io.git' # 推荐使用SSH地址
      branch: main
  4. 请进入您在 GitHub 上的 Prorise-cool.github.io 仓库页面。

    点击顶部的 Settings (设置) 选项卡。

    在左侧菜单中,点击 Pages

    在打开的页面中,找到 Build and deployment (构建和部署) 部分。

    Source (源) 下面,请确保选项是 Deploy from a branch (从分支部署)。

    Branch (分支) 下面,请再次确认下拉菜单中选择的是 main,并且文件夹选项选择的是 /(root)

  5. 执行部署

    • 在终端中运行:
    1
    hexo clean && hexo g -d
  6. 获取您的测试URL

    • 等待一两分钟让 GitHub Pages 完成部署后,在浏览器中访问您的线上地址:
      https://Prorise-cool.github.io
    • 如果能看到您的博客,说明临时部署成功!这个地址就是我们下一步要用来测试的地址。
  • 如果这里的设置不正确,请修改并点击 Save
  • 如果这里的设置已经是正确的,那么通常只是部署生效的延迟

第二步:使用Lighthouse进行性能评测

现在我们有了公开的网址,可以开始正式评测了。

  1. 在 Chrome 开发者工具中运行(最推荐)

    • 在 Chrome 浏览器中,打开您刚刚部署好的线上博客地址。
    • F12 打开开发者工具,找到并切换到 Lighthouse 选项卡。
    • 在“Device (设备)”中,选择 Mobile(手机)。
    • 在“Categories (类别)”中,勾选 Performance(性能)以及其他您关心的项目。
    • 点击 Analyze page load(分析页面加载)按钮。
  2. 解读报告核心指标

    • 测试完成后,您会得到一份详细报告。请重点关注 Performance 分数,以及下面这几个核心指标:
指标名称 (Metric)测量内容理想得分 (Ideal Score)
FCP (First Contentful Paint)浏览器渲染出第一个内容的时间1.8秒 以内
LCP (Largest Contentful Paint)视口内最大可见元素加载完成的时间2.5秒 以内
TBT (Total Blocking Time)主线程被长任务阻塞的总时间200毫秒 以内
CLS (Cumulative Layout Shift)页面加载过程中视觉元素的“跳动”量0.1 以下
  1. 关注优化建议
    • 报告中最有价值的部分是下方的 “Opportunities (机遇)”“Diagnostics (诊断)”
    • 它会明确告诉您哪些图片过大、哪些JS阻塞了渲染、哪些CSS没有被使用等等。您可以根据这些具体的建议,回头再去调整您的配置或代码。

后续步骤

在您根据Lighthouse的报告,对您的博客进行了多轮的优化和测试,并对性能分数感到满意之后,我们才算真正完成了“性能优化”这个章节。

到那时,真正的“上一个服务器”——即将您的博客部署到您自己的服务器并绑定 prorise.com 这样的顶级域名——才会是我们的下一个大主题。