1 背景
小米在MIUI 13
发布的同时,也发布了全新字体MiSans
。在将云服务首页项目的字体替换为MiSans
后,利用Google
的Lighthouse
做网站性能测试时发现,字体的加载阻塞了页面的渲染。如下图所示:
2 解决方案
2.1 preload
通过link
标签的rel="preload"
配置进行内容预加载,待资源加载完成后,再修改link
标签的rel
的配置为stylesheet
进行页面字体的渲染。
<link
rel="preload"
href="https://font.sec.miui.com/font/css?family=MiSans:400,500,600,700:Chinese_Simplify,Latin,Chinese_Traditional&display=swap"
as="style"
onload="this.onload=null;this.rel='stylesheet'"
/>
<!-- 禁止JS执行的浏览器直接加载字体资源 -->
<noscript>
<link
href="https://font.sec.miui.com/font/css?family=MiSans:400,500,600,700:Chinese_Simplify,Latin,Chinese_Traditional&display=swap"
rel="stylesheet"
type="text/css"
/>
</noscript>
这种方案需要浏览器支持preload
属性,存在部分浏览器不兼容性的问题,需要pollfill
来解决(preload兼容性)。
2.2 media
与 2.1
的思路类似,可以借助link
的media
属性来实现字体资源的延迟加载。其原理为浏览器在渲染阶段会跳过带有media="print"
配置的CSS
的加载,等到页面加载完成后再加载对应的资源。
<link
rel="stylesheet"
href="https://font.sec.miui.com/font/css?family=MiSans:400,500,600,700:Chinese_Simplify,Latin,Chinese_Traditional&display=swap"
media="print"
onload="this.media='all'"
/>
<!-- 禁止JS执行的浏览器直接加载字体资源 -->
<noscript>
<link
href="https://font.sec.miui.com/font/css?family=MiSans:400,500,600,700:Chinese_Simplify,Latin,Chinese_Traditional&display=swap"
rel="stylesheet"
type="text/css"
/>
</noscript>
几乎所有主流浏览器都支持media
属性(link media兼容性)。
3 总结
使用以上方案中的任意一种后,Lighthouse
的页面渲染阻塞警告都会消失,并且FCP
和SI
指标都有所减少。从用户体验来看的话,页面的白屏时间会减少。
阻塞 | preload | media | |
First Contentful Paint | 0.5s | 0.2s | 0.2s |
Speed Index | 0.5s | 0.3s | 0.3s |