阅读 432

前端性能其一:使用Lighthouse对掘金主站进行性能分析

作为前端开发,我们时常讨论性能分析,若是要聊如何进行性能优化,我们总能说出一些名词:

  • 压缩外部资源
  • 对JavaScript进行分包
  • 对各种外部资源进行懒加载
  • 请求链路上的优化(缓存,cdn,http2诸如此类)

但是说这么多的优化手段,我们到底在优化什么?加载时间是多少才算作快?用什么作为我们优化的参照物呢? 当我们接收到一个性能优化的任务,用什么去衡量成果?

本文的目的就是通过一个案例分析了解前端性能的指标及其对应的优化手段。

什么是Lighthouse

根据刚刚疑问,前端性能优化的难点在于制定指标,并且将其具现化为数据展示,如果有个评分最好了,那我们就只要努力提供我们网站的评分就行了。

Lighthouse就是拥有这些能力的一个工具,何为Lighthouse?它是这么介绍自己的:

Lighthouse analyzes web apps and web pages, collecting modern performance metrics and insights on developer best practices.

Ligthhouse收集了我们感兴趣的大部分数据,并对其进行了分析,将分析结果以可视化的方式展示给开发者,甚至还指出了我们可以优化的地方。

这是Lighthouse分析结果的部分截图,可以看到它为我们的网站的几个方面作出了评分:性能、易用性、最佳实践、SEO、PWA支持程度。

那么这么好的一个东西,我们应该怎么使用呢?

通过Chrome Devtool使用

这种好东西,老早就集成到Devtool上了,我们可以轻松使用Devtool对网站进行性能分析。

我们可以看到,Lighthouse支持模拟移动端,还能限制网速和CPU。Devtool方便我们随时的测试我们的界面,但是终究还是在开发机器上,被机器的性能网络和地域所限制。

所以Lighthouse还提供的cli的方式测试界面。

通过node CLI使用

目前Lighthouse已经发布了npm包,我们可以轻松通过下面的命令对界面进行测试:

$ npm i lighthouse -g
$ lighthouse https://juejin.im/ --view
复制代码

既然是npm包,Lighthouse还开放了对其进行二次开发的接口,对Lighthouse进行配置和管理。

你可以通过脚本轻松的集成Lighthouse到自己的ci/cd流程中:

// 运行代码后,访问/performance会返回掘金主站的性能分析结果
const Koa = require('koa');
const lighthouse = require('lighthouse');
const chromeLauncher = require('chrome-launcher');

function launchChromeAndRunLighthouse(url, opts, config = null) {
  return chromeLauncher.launch({chromeFlags: opts.chromeFlags}).then(chrome => {
    opts.port = chrome.port;
    return lighthouse(url, opts, config).then(results => {
      return chrome.kill().then(() => results.report)
    });
  });
}

app.use(async (ctx, next) => {
  if(ctx.path.match('/performance')) {
    const report = await launchChromeAndRunLighthouse('https://juejin.im/', { output: 'html' });
    ctx.body = report;
    return;
  }
  return next();
});

app.listen(8080)
复制代码

通过Chrome 插件使用

除此上述两种使用方法,Lighthouse还提供了Chrome 插件的版本,本质上和Devtool的使用方式差别不大,这里不做详细介绍。

使用Lighthouse对掘金主站进行性能分析

讲那么多,我们还是要整个实战来的有用。我这里选择了掘金作为小白鼠,让我们一起看看掘金主页的性能如何?有哪些需要优化的地方(我机器比较烂所以分数会比较低(:)。

我这里使用node CLI的形式进行性能测试,这里测试的是桌面端(方便我们通过控制台查看优化方案),执行$ lighthouse https://juejin.im/ --emulated-form-factor desktop --view,这里我们只截取性能部分进行分析。

可以看到掘金主站的性能评分为64,在讨论这个评分之前我们先了解一下几个指标:

  • First Content Paint:浏览器第一次文本绘制的时间,这个指标对于没有使用ssr技术的web app意义并不大,因为第一绘制发生的时间通常JS还没加载完毕。
  • First Meaningful Paint:浏览器有意义的内容的绘制时间,比如博客的博文主体绘制时间,具体的值为绘制内容单位时间增加最多的时间点。
  • Speed Index: 浏览器出现可视内容的时间(通常出现在浏览器初次提交绘制指令之后),该指标捕获的是页面出现像素点的时间。
  • First CPU idle:主线程初次空闲时间,意味着此时的用户交互可以被处理,比如react的第一次异步调度就可能出现在这里。
  • Time to Interactive:可交互时间,这个指标并不是指的最早的可交互时间,而是可流畅交互的时间,具体的值为FMP之后,5秒后没有long task执行(50ms以上的任务)的时间
  • Max Potential First Input Delay:用户可能体验到的最大无响应时间,具体的值就是最长的task执行时间。

了解完这几个指标后,我们可以看到掘金的内容展示速度是比较优秀的,问题在于可交互时间,不过掘金也不是一个强交互的产品,可能不大关心。

我们秉承学习的心态来看一下有哪些优化点。

可以优化的地方

一开始说了,Lighthouse不仅能测试性能问题,还能告诉我们如何解决性能问题;那我们看看问题和优化方法:

其中Opportunities指的是优化机会,Diagonstics指的是现在存在的问题。

优化机会层面,我看到了我们许多属性的名词:

  • 使用下一代图片编码格式使用图片,这里指的是webp格式,显然第一张图片也没压缩,我看是小册的广告图片,有可能是运营上传的时候没压缩,可以考虑管理平台支持。
  • 减少阻塞渲染的资源,这里指的是CSS文件(css加载完成后,js的下载不会阻塞渲染),可以看到iconfont的体积很小,加载却慢这种时候就要优化网络相关的时间如:DNS lookup、tcp connect、TTFB。
  • 提前和要拉取资源的源建立链接,在link标签使用preconnect,dns-prefetch,dns-prefetch等属性进行网络上的链接操作(eg:<link ref="preconnect" href="my.cdn.com">)。
  • Enable text compression指的是文本资源要压缩后传输如:gzip
  • Properly size images指的是使用合适尺寸的图片资源,比如iOS下系统会根据分辨率选择@2x还是@3x之类的图片,依然可以从运营系统层面进行支持(上传@3x图片自动生成@2x和@1x的图片)
  • Defer offscreen images指的是懒加载不在可视区域上的图片。

根据这些小点,我们就能进行一波简单的优化,然后再进行一波测试,取均值就能得到大概的优化结果了。

解决存在的问题

刚刚只是讨论我们还存在哪些性能点可以进行优化,但有时候界面的性能差不是因为还有优化点没做,而是现有代码出现了问题;同样Lighthouse也指出了我们的问题。

我们也一个个瞧一下,尽自己的一份力量帮助掘金前端加班(:

  • 确保字体文件加载过程中,字体能够显示。可能很多人对这点干掉懵逼:如果我们的样式使用了第三方字体,在字典加载完成前浏览器会延迟渲染字体(Chrome会延迟三秒),如果字体文件过大,下载时间过长网页内容就会空有架子没有文字。解决方案:字体加载方案,当然这里掘金使用的是字体图标,没啥槽点。
  • 尽量减少主线程的任务,主线程的任务比我们想象的要多的多,我们能比较好优化点也只有:脚本执行/解析/编译;其余几项都与我们要输出的内容有关,所以能优化的比较有限。脚本的执行耗时最多,也是最好优化的,实际上我们在应用入口中常常初始化太多东西,为了方便后续同步使用这些资源。
    • 使用webpack对初始化脚本进行切割,用异步的方式使用这些脚本资源
  • 定制合理的缓存策略,这里主要嫌弃掘金的缓存时长太短,这种策略见仁见智,不做讨论,具体的缓存策略网上也有很多了。
  • DOM太多了,会导致应用比较吃内存,layout和reflow的性能消耗过高,这种问题主要从开发层面进行预防,比如codereview。

其实Lighthouse提供了不止这几种优化指标和缺陷报告,限于篇幅本篇文章就暂时分析这些,其实Lighthouse还有很多好玩的功能,使用起来也是很轻便的。

更多Lighthouse的使用方法:web.dev

Lighthouse的盲区

事实上Lighthouse是一个性能测试工具,并不能完全代表用户的真实体验,当我们使用Lighthouse的时候,基于都是宿主机器的性能结果,虽然我们可以限制网速和CPU等等,但和现实还有有所差距。

虽然有这些问题,但不妨碍Lighthouse是一个优秀的工具,Lighthouse可以作为集成性能测试工具。为我们提供标准的性能报告,在使用过程中我们可以将其集成于CD流程,作为测试的一种,保证我们上线的功能在大多环境下有着优秀的表现。

那如何进行真实环境的性能指标收集和分析呢?下一篇见

关注下面的标签,发现更多相似文章
评论