风和日丽: 我正笑嘻嘻地抓着我炫酷的ikbc键盘疯狂的敲着Bug.
晴天霹雳: 被拉进了一个群,产品说我做的网站很卡,需要做性能优化.
难以置信: 我可是用尊贵的Vue3+Ts开发的呢 (手动狗头).
十分抗拒: 迫于yin威,我给网站做了体检和手术.
市面上的体检套餐有很多种,但其实都是换汤不换药.那药(标准)是什么呢?我们会在下面说明.这里我选择了谷歌亲儿子"灯塔"(LightHouse)进行性能体检.
为什么我说大多体检套餐都是换汤不换药呢?我们先从灯塔的计分规则说起:
从上面中我们可以看到灯塔v6/v7版是通过几种性能指标及不同权重来进行计分的.这几种指标主要是根据PerformanceTiming和PerformanceEntry API标准进行定义.市面上大多体检套餐也是基于这些指标定制的.接下来我们来了解下这些指标的含义吧.
渲染第一个元素(文本、图片、canvas...)的时间点
首屏展现时间
渲染可视区域内最大内容元素的时间点
页面资源加载成功并能响应用户交互的时间点
FCP到TTI之间,主线程被long task(超过50ms)阻塞的时间之和
累计布局偏移值
用户第一次在页面进行交互(点击链接、按钮、自定义js事件),到浏览器实际开始处理这个事件的时间
谈到用户体验与性能指标,顺便提下Core Web Vitals.
2020年5月,Google针对网站使用体验推出了一套核心指标标准(Core Web Vitals).由三项指标构成:
为什么不是别的指标呢 ? 因为这套标准主要从以下三个维度进行评估:
[视觉稳定性] : CLS
开发者可利用以下几种工具对Core Web Vitals进行监测:
由于FID需要一个真实用户的交互,所以无法用实验数据测试.为了能在实验数据下测试FID,通常会用TBT (Total Blocking Time).虽然他们测量的内容不同,但改善TBT通常也能改善FID.
不检不知道,一检吓一跳.6个"重要器官"凉了一半...是时候对它动个手术了!
既然是性能手术,方案就主要以性能指标作为维度,主要分为以下几个点:
优化未设置尺寸的图片元素
改善建议里提到了一项优先级很高的优化就是为图片元素设置显式的宽度和高度,从而减少布局偏移和改善CLS.
<img src="hello.png" width="640" height="320" alt="Hello World" />
自定义字体文件加载期间保持可见状态
改善建议里提到使用CSS font-display属性确保自定义字体文件在加载期间可见.
这是因为网站下载自定义字体文件需要一段时间,而不同浏览器此时的行为是不同的.一些浏览器在加载自定义字体时会隐藏文字,这种称之为FOIT(Flash Of Invisible Text).而一些浏览器会显示降级字体,这种情况称之为FOUT(Flash Of Unstyled Tex).这两种行为会导致"字体闪烁问题",影响视觉稳定性 (CLS).
我的处理方法是直接设置font-display:swap;这个属性能确保字体在加载时间可见.虽然还是会引发FOUT,但是相比FOIT,FOUT对视觉稳定性的影响会小一些.
更好的方案应该是预加载(preload)字体文件.让字体下载有更高概率赶在FCP之前,从而避免FOIT/FOUT.
@font-face {
font-family: 'Hello-World';
src: url('../font/Hello-World.otf') format('OpenType');
/* swap:如果设定的字体还未可用,浏览器将首先使用备用字体显示,当设定的字体加载完成后替换备用字体 */
font-display:swap;
}
我们产品中有一个顶部动态插入的元素,这个元素会导致网站整体布局下移.从而造成了较大的布局偏移.跟产品及ui py交易后,我们友好地对这个元素进行了调整.将该元素脱离文档流,采用固定定位的方式进行展示.从而解决该问题.
改善建议中提到应避免使用非合成动画,非合成动画会使得页面变得混乱并增加CLS.关于这个优化建议我觉得应该具体场景具体分析,不应该"因噎废食".毕竟目前能被composited的css属性只有transform & opacity.当然这也在提醒我们平时在做CSS动画时应注意优化 (比如常见的使用transform替代top).
替换最大内容绘制元素
在改善建议中,我发现网站的最大内容绘制元素是谷歌地图中的一个图块元素.这也难怪LCP指标的数据表现不理想了,原因: 链路过长 - 下载谷歌地图Js sdk => 初始化谷歌地图=> 绘制 .
于是,我决定对最大内容绘制元素进行修改,从而提升LCP时间.我喵了一眼Largest Contentful Paint API 关于该元素类型的定义,将"目标"锁定到了一个loading元素 (绘制成本低: 默认渲染,不依赖任何条件和判断).经过我对该元素的尺寸动了手脚后(变大),该元素成功"上位".
异步加载谷歌地图Js sdk
原先加载谷歌地图Js sdk是通过动态添加script标签同步加载的.这样做的缺点其实是很明显的:
<script
src="//maps.googleapis.com/maps/api/js"
type="text/javascript"
defer
></script>
lottie动画库
站点只有一个动画效果的实现用到该库,跟产品、ui又一顿py后,我们决定牺牲一点"视觉效果".移除lottie library,改用CSS3实现.
ant-design-vue中内置的momentjs依赖
momentjs的语言包(locale)体积非常大,而站点并无国际化需求.所以这里我直接使用webpack IgnorePlugin对语言包进行忽略.
经过优化,bundle体积(gizp前)由原来的1.8MB减小至1.3MB.
网站使用的是Vue做的客户端渲染.这也意味着FCP过程会有点"漫长". (初始化Vue实例等一系列工作需要占用主线程执行Js).这里我"自作聪明"地在html文件添加了"透明文本占位符",抢占FCP时间.这个骚操作我个人认为有点抖机灵,大家可以选择性无视...
<div id="app">
<!-- 占位符 -->
<p style="color:#fff;">Hello World</p>
</div>
除了针对上面几个指标维度进行优化外,我还做了几点优化,这里简单提一下:
说了那么多"废话",那手术结果究竟如何呢 ? 是华丽变身还是"反向一Q日神仙"呢 ? 直接上图:
通过上图我们可以看到各项指标及评分都有质的飞跃,虽然我"不要脸地截了个最高分" (LightHouse每次评分会有波动,实际效果是由原来的50-70分涨到了70-90分) !!!
平时我们侃侃而谈的性能优化点往往也是我们最容易忽略的点.性能优化也绝非一蹴而就,需要我们在日常开发中不断去发现和优化.路漫漫其修远兮...
如果你觉得我的文章对你有帮助,欢迎关注我一起玩耍~
在使用Dreamweaver进行WEB标准化布局的过程中,如果我们需要对某些代码部分进行...
今天这篇过来人的宝贵经验,作者有过7年的技术管理经验,最多时带了80+人,现就...
写这个效果,可以熟悉以下: 1、相对定位中的绝对定位; 2、CSS 针对浏览器 HACK...
如何使整个页面内容居中,如何使高度适应内容自动伸缩。这是学习CSS布局最常见的...
想做个页面用到css3的圆角和阴影效果,但ie浏览器不支持,之前也听说有插件可以...
往css文件里写入 复制代码 代码如下: 01.html{ filter: grayscale(100%); -webki...
对404都是避之不及,何来体验之说?原因可能是大多数404页面 都太粗糙了,而今天...
手机端页面的底部导航栏,仿照安卓、IOS等Apps应用底部导航栏的设计。许许多多的...
有时候需要在一张图片上设置几个区域,鼠标点击图片的不同区域可以进入不同的页...
分析XML文档可通过程序来做,分析器有两大类,一种是事件驱动的,一种是基于树模...