“作为博客园的使用者而不是开发者,就不能对博客进行调优了?看好了,我只示范一次。” —— 我说的
0x00 大纲
0x01 前言
用过很多博客和写作平台,但是最终还是选择了博客园,毕竟,自定义 CSS 和自定义 JS 是真的香!某天突发奇想,决定对自己的博客进行下优化,现将其中的一些心得与大家分享。里面的一些方式方法可能不通用,但是思路可能会对各位有所启发。说实话,自己的本职工作并不是前端,不想搞那么复杂,就用 Edge 浏览器的开发者工具里的 lighthouse 评分和加载时间作为优化基准。
以博客的使用者而不是开发者身份去进行优化,究竟能做到何种程度,让我们拭目以待。
0x02 性能调优
减少加载项
-
(减少加载时间约40ms)在博客园后台-选项页面中取消勾选“启用数学公式支持”,点击“保存”按钮,刷新页面后至少可以减少以下几个加载项,节省页面加载时间约40ms:
- MathJax.js
- TeX-AMS-MML_HTMLorMML.js
- extpfeil.js
- mediawiki-texvc.js
-
(减少加载时间约50ms)在博客园后台-设置页面中“代码高亮”部分取消勾选“显示行号”,如果你用的是 prism 引擎,可以减少两个加载项:
- prism-line-numbers.css
- prism-line-numbers.js
减少网络传输量
-
博文图片尽量采用 PNG 格式,内容色彩较少时可以使用索引颜色压缩。举个栗子,这是两张内容和分辨率一样,格式不同的两张二维码图片,可以看到 PNG 格式比 JPG 格式文件大小相差一个数量级:
降低渲染复杂度
博文和自定义 HTML 部分尽量减少 DOM 数量和嵌套。比如:
<div class="hint">HELLO WORLD</div>
如果能满足效果,就不要写成:
<div class="container">
<div class="text">
<span>HELLO WORLD</span>
</div>
</div>
压缩资源文件
对于自定义的 CSS 或 JS 文件进行压缩,如果引用外部的 CSS 或 JS ,尽量使用其 min 版本。能省一个字节是一个字节。
减少字体引用
对于自定义的 CSS,尽量使用统一的字体定义,避免引入大量不同的字体。
body {font-family: Lato, PingFang SC, Microsoft YaHei, sans-serif;font-size: 14px;font-weight: 300;}
对于博客园中一些带了字体定义样式的部分,可以予以覆盖,比如文章支持数和反对数里面引入了 Verdara 字体,可以通过继承body
中定义的font-family
进行覆写:
.burynum,.diggnum{font-family:inherit;}
改善 CLS 布局偏移
CLS(Cumulative Layout Shift),累积布局偏移,是页面在整个生命周期中发生的每个元素布局变化的分数总和(分数越低越好)。这些变化会影响用户正确阅读内容和与页面交互的能力。所谓改善 CLS 就是要尽量保持页面上元素位置的稳定,避免页面元素在渲染过程中大幅度偏移初始位置。
常见的影响 CLS 的因素有:
- 未指定宽高的图片。
- 动态插入的内容(广告、iframe等嵌入元素)。
- Web 字体的加载。
- 阻塞 DOM 更新的操作(通常是关键样式或关键脚本加载等待网络响应)。
CLS 对性能总分的影响很大,由于每个人的自定义样式不尽相同,所以这一块只能根据个人情况对症下药了:
-
(降低 CLS 分数 0.002)尽可能地为图片元素设置明确的宽度值和高度值,以减少布局偏移并改善 CLS,比如首页的头像和名片:
<!-- 头像 --> <img width="230px" height="230px" alt="avatar" class="esa-profile-avatar" src="https://images.cnblogs.com/cnblogs_com/mylibs/1647185/o_200214034545avatar.png"> <!-- 名片 --> <img width="230px" height="230px" class="esa-profile-avatar" title="商务合作请添加微信" alt="商务合作请添加微信" src="https://images.cnblogs.com/cnblogs_com/mylibs/1647185/o_221216003723_card(wechat).png">
-
在博客园后台-设置页面中“页脚 HTML 代码”处引入自定义 JS,而不是公告栏或者页首。这也是官方推荐做法。
-
(降低 CLS 分数 0.006)通过 CSS 而不是 JS 控制侧边栏的显示/隐藏:
为了获得更好的阅读效果和较大的阅读版式,原先通过自定义 JS 动态隐藏了文章详情页的侧边栏,大概是这样的代码:
if($("#post_detail").length > 0) { $("#sideBar").hide(); $(".forFlow").css({"margin-left: 0 !important"}); } else { $("#sideBar").show(); $(".forFlow").css({"margin-left: 260px"}); }
由于自定义 JS 的加载时机较晚,所以页面难免出现大幅的偏移调整,导致 CSL 分数暴涨。这样子做是有历史原因的,因为最开始 CSS 还没有父选择器,不能通过子元素类型来选择父元素,在博客这里也就不能通过
div.forFlow
容器中的子元素内容来控制div.forFlow
的偏移和mainContent
的兄弟元素侧边栏sideBar
,好在后来:has()
伪类选择器横空出世,我可以这样子通过 CSS 来直接控制了:#mainContent .forFlow { margin-left: 260px; max-width: 960px; } .forFlow:has(#post_detail) { margin-left: 0 !important; } #mainContent:has(#post_detail)+#sideBar { display: none !important; }
当作为博客主页显示时,由于
#post_detail
元素不存在,因此,div.forFlow
容器会向左偏移260像素,为侧边栏留出显示空间;当用户点击文章进行阅读时,#post_detail
元素将被加载,两个has()
伪类选择器生效,达到取消偏移量和隐藏侧边栏的效果,缺点就是到目前为止,不是所有浏览器都支持。比如火狐就不支持……在不支持的浏览器上,它是可容错的,相当于这两个样式不存在,不会影响页面的可访问性。以我自己的博客为例,可以看到在 Edge 和 Chrome 浏览器上,文章详情页中侧边栏是隐藏的,而在火狐浏览器上,侧边栏依然存在。
改善 FCP 首次内容绘制
FCP(First Contentful Paint),首次内容绘制,该指标测量页面从开始加载到页面内容的任何部分在屏幕上完成渲染的时间。对于该指标,“内容”指的是文本、图像(包括背景图像)、元素或非白色的元素。所谓改善 FCP 就是要让浏览页面的用户尽快地看到页面内容,即使此时页面还未完全渲染完成——以此优化用户体验。
能做的也不多,暂时发现比较有优化价值的是 Web 字体,可以利用 font-display 这项 CSS 特性,确保文本在网页字体加载期间始终对用户可见。比如在用到了自定义 Web Font 的地方,加上font-display: swap;
,注意要在@font-face
定义里面声明,否则无效,像这样:
@font-face {font-family: Material Symbols Outlined;font-display: swap;font-style: normal;font-weight: 300;src: url(https://cdn.cnblogs.com/iconfonts/iconfont-chnmig.ttf) format("truetype");}
直接减少 FCP 时间约60ms!但这还不是极限,大部分小伙伴引入的自定义字体多是 IconFont 之类的图标字体,但是一个图标字体里面可能有上百个冗余图标,我们往往只使用了其中的某几个。利用神器icomoon,我们可以只将自己用到的图标封装成自定义的字体,甚至可以将其以 base64 编码的形式,内嵌到自定义样式中,这可以带来数量级的加载时间提升(取决于原字体的大小)。以我自己的博客为例,将仅用到的12个图标转换成自定义字体后,首页的 FCP 时间减少了将近200ms:
@font-face {font-family: 'iconfont-mylibs';src: url('data:font/woff;charset=utf-8;base64,(限于篇幅,此处省略数据定义)') format('woff');font-weight: 300;font-style: normal;font-display: swap;}
0x03 无障碍阅读改造
此部分主要参照标准为 WCAG 2.1 (AA), WCAG 2.0 (AA)
媒体查询
通过@media
媒体查询适配不同分辨率的终端设备,以保证用户在不同的设备上,都能获得较佳的浏览体验。
色彩分离度
原主题在白天和黑夜模式共用一个主题颜色#2d8cf0
,色彩分离度不是很好,尤其是小字体的时候,很容易导致阅读困难。遂将原主题白天模式前景色调整为#0f73e1
,使其与背景色有更强的区分度,夜间模式时保持原来的颜色不变。关于采用何种前景色和后景色才具有良好分离度,可以使用这个链接里面的工具,提供动态参照对比。
正确使用鼠标手势
在自定义 HTML 和样式时,注意正确使用鼠标手势。比如在超链接和按钮上使用手形光标,在可选文本上使用文本光标,在非交互元素上使用默认光标等等。
类型 | 说明 |
---|---|
auto | 默认值。浏览器根据当前情况自动确定鼠标光标类型。 |
all-scroll | 有上下左右四个箭头,中间有一个圆点的光标。用于标示页面可以向上下左右任何方向滚动。 |
col-resize | 有左右两个箭头,中间由竖线分隔开的光标。用于标示项目或标题栏可以被水平改变尺寸。 |
crosshair | 简单的十字线光标。 |
default | 客户端平台的默认光标。通常是一个箭头。 |
hand | 竖起一只手指的手形光标。就像通常用户将光标移到超链接上时那样。 |
move | 十字箭头光标。用于标示对象可被移动。 |
help | 带有问号标记的箭头。用于标示有帮助信息存在。 |
no-drop | 带有一个被斜线贯穿的圆圈的手形光标。用于标示被拖起的对象不允许在光标的当前位置被放下。 |
not-allowed | 禁止标记(一个被斜线贯穿的圆圈)光标。用于标示请求的操作不允许被执行。 |
pointer | 和hand一样。竖起一只手指的手形光标。就像通常用户将光标移到超链接上时那样。 |
progress | 带有沙漏标记的箭头光标。用于标示一个进程正在后台运行。 |
row-resize | 有上下两个箭头,中间由横线分隔开的光标。用于标示项目或标题栏可以被垂直改变尺寸。 |
text | 用于标示可编辑的水平文本的光标。通常是大写字母I的形状。 |
vertical-text | 用于标示可编辑的垂直文本的光标。通常是大写字母I旋转90度的形状。 |
wait | 用于标示程序忙用户需要等待的光标。通常是沙漏或手表的形状。 |
*-resize | 用于标示对象可被改变尺寸方向的箭头光标。w-resize|s-resize|n-resize|e-resize|ne-resize|sw-resize|se-resize|nw-resize |
url (url) | 用户自定义光标。使用绝对或相对url地址指定光标文件(后缀为.cur或者.ani)。 |
0x04 小结
在经过一系列的努力后,我完成了几乎所有能做的改造。这是最终首页的灯塔评分:
达到这个分数并不容易,尤其是在引入了一系列自定义的东西之后。报告中会告诉你还有哪些地方可以优化,遗憾的是,作为一个使用者,只能止步于此了。即使在博客园后台-设置页面中“页面定制 CSS 代码”部分勾选了“禁用模板默认 CSS”,还是会有一部分资源被强制加载:
这些部分看起来很有搞头,可惜暂时没有找到合适的方法,如果有机会再尝试冲击百分吧。