文章目录
- 1、基本指标介绍
- 2、Performace分析
- 2.1 performance属性
- 2.2 使用performace计算
- 2.3 Resource Timing API
- 2.4 不重复的耗时时段区分
- 2.5 其他组合分析
- 2.6 JS 总加载耗时
- 2.7 CSS 总加载耗时
- 3、lighthouse基本使用
- 3.1 使用Chrome插件lighthouse
- 3.2 使用Chrome浏览器开发者工具(F12)自带功能
- 3.3 使用npm包lighthouse
- 3.4 Lighthouse运行的生命周期
- 3.5 Lighthouse报告的指标分析
- 3.5.1 性能(Performance)
- 3.5.1.1 影响评分的性能指标
- 3.5.1.2 性能指标评分的计算
- 3.5.2 访问无障碍(Accessibility)
- 3.5.3 最佳实践(优化)(Best Practice)
- 3.5.4 搜索引擎优化(SEO)
- 3.5.5 PWA(Progressive Web App)
- 4、Lighthouse优化
1、基本指标介绍
首先前端性能指标一般分为以下几种:
- 首屏绘制(First Paint,FP)
- 首屏内容绘制(First Contentful Paint,FCP)
- 可交互时间(Time to Interactive,TTI)
- 最大内容绘制(Largest Contentful Paint,LCP)
- 首次有效绘制(First Meaning Paint, FMP)
FP 是时间线上的第一个“时间点”,是指浏览器从响应用户输入网址地址,到浏览器开始显示内容的时间,简而言之就是浏览器第一次发生变化的时间。
FCP(全称“First Contentful Paint”,翻译为“首次内容绘制”),是指浏览器从响应用户输入网络地址,在页面首次绘制文本,图片(包括背景图)、非白色的 canvas 或者SVG 才算做 FCP,有些文章说 FCP 是首屏渲染事件,这其实是不对的。
TTI,翻译为“可交互时间”表示网页第一次完全达到可交互状态的时间点。可交互状态指的是页面上的 UI 组件是可以交互的(可以响应按钮的点击或在文本框输入文字等),不仅如此,此时主线程已经达到“流畅”的程度,主线程的任务均不超过50毫秒。在一般的管理系统中,TTI 是一个很重要的指标。
FMP(全称“First Meaningful Paint”,翻译为“首次有效绘制”表示页面的“主要内容”开始出现在屏幕上的时间点,它以前是我们测量用户加载体验的主要指标。本质上是通过一个算法来猜测某个时间点可能是 FMP,但是最好的情况也只有77%的准确率,在lighthouse6.0 的时候废弃掉了这个指标,取而代之的是 LCP 这个指标。
LCP(全称“Largest Contentful Paint”)表示可视区“内容”最大的可见元素开始出现在屏幕上的时间点。
2、Performace分析
2.1 performance属性
浏览器提供的performace API,这也是性能监控数据的主要来源,performace提供高精度的时间戳,精度可达纳秒级别,且不会随操作系统时间设置的影响。目前主流浏览器都支持。
- window.performance.navigation: 页面加载还是刷新,发生了多少次重定向,
- window.performance.timing: 页面加载的各阶段时长,
- window.performance.memory:基本内存使用情况,Chrome添加的一个非标准扩展。
- window.performance.timeOrigin:性能测量开始时的时间高精度时间戳。
2.2 使用performace计算
performance.getEntriesByType(“navigation”);
- 重定向次数:performance.navigation.redirectCount
- 重定向耗时: redirectEnd - redirectStart
- DNS 解析耗时: domainLookupEnd - domainLookupStart
- TCP 连接耗时: connectEnd - connectStart
- SSL 安全连接耗时: connectEnd - secureConnectionStart
- 网络请求耗时 (TTFB): responseStart - requestStart
- 数据传输耗时: responseEnd - responseStart
- DOM 解析耗时: domInteractive - responseEnd
- 资源加载耗时: loadEventStart - domContentLoadedEventEnd
- 首包时间: responseStart - domainLookupStart
- 白屏时间: responseEnd - fetchStart
- 首次可交互时间: domInteractive - fetchStart
- DOM Ready 时间: domContentLoadEventEnd - fetchStart
- 页面完全加载时间: loadEventStart - fetchStart
- http 头部大小: transferSize - encodedBodySize
2.3 Resource Timing API
performance.getEntriesByType(“resource”);
// 某类资源的加载时间,可测量图片、js、css、XHR
performance.getEntriesByType("resource").forEach(resource => {if (resource.initiatorType == 'img') {console.info(`Time taken to load ${resource.name}: `, resource.responseEnd - resource.startTime);}
});
总结:
基于 performance 我们可以测量如下几个方面:mark、measure、navigation、resource、paint、frame。
let p = window.performance.getEntries();// 重定向次数
performance.navigation.redirectCount// JS 资源数量
p.filter(ele => ele.initiatorType === "script").length// CSS 资源数量
p.filter(ele => ele.initiatorType === "css").length// AJAX 请求数量
p.filter(ele => ele.initiatorType === "xmlhttprequest").length// IMG 资源数量
p.filter(ele => ele.initiatorType === "img").length//总资源数量
window.performance.getEntriesByType("resource").length
2.4 不重复的耗时时段区分
- 重定向耗时: redirectEnd - redirectStart
- DNS 解析耗时: domainLookupEnd - domainLookupStart
- TCP 连接耗时: connectEnd - connectStart
- SSL 安全连接耗时: connectEnd - secureConnectionStart
- 网络请求耗时 (TTFB): responseStart - requestStart
- HTML 下载耗时:responseEnd - responseStart
- DOM 解析耗时: domInteractive - responseEnd
- 资源加载耗时: loadEventStart - domContentLoadedEventEnd
2.5 其他组合分析
- 白屏时间: domLoading - fetchStart
- 粗略首屏时间: loadEventEnd - fetchStart 或者 domInteractive - fetchStart
- DOM Ready 时间: domContentLoadEventEnd - fetchStart
- 页面完全加载时间: loadEventStart - fetchStart
2.6 JS 总加载耗时
// JS总加载耗时
const per = window.performance.getEntries();
let jsR = per.filter(ele => ele.initiatorType === "script");
Math.max(...jsR.map((ele) => ele.responseEnd)) - Math.min(...jsR.map((ele) => ele.startTime));
2.7 CSS 总加载耗时
// CSS总加载耗时
const per = window.performance.getEntries();
let cssR = per.filter(ele => ele.initiatorType === "css");
Math.max(...cssR.map((ele) => ele.responseEnd)) - Math.min(...cssR.map((ele) => ele.startTime));
3、lighthouse基本使用
Lighthouse 是一个网站性能测评工具, 它是 Google Chrome 推出的一个开源自动化工具,能够对 PWA 和网页多方面的效果指标进行评测,并给出最佳实践的建议以帮助开发者改进网站的质量。它能够生成一个有关页面性能的报告,通过报告我们就可以知道需要采取哪些措施来改进应用的性能和体验。
3.1 使用Chrome插件lighthouse
(注意,插件的下载和报告的查看可能都需要墙后才能看)
可以在 Chrome 扩展商城里搜索 lighthouse ,或者通过以下地址来下载 lighthouse 添加至 Chrome浏览器中。
插件商城下载地址:https://chrome.google.com/webstore/detail/lighthouse/blipmdconlkpinefehnmjammfjpmpbjk
操作方式:
先访问需要评估的网站,比如 http://www.baidu.com,然后点击灯塔按钮,选择 generate report 即可。lighthouse 会运行一系列的测试审查这个页面,然后它会把关于页面执行的一些性能指标以报告的形式展示给你。你可以参考这份报告中的一些指标提示来提升你的网站应用。Lighthouse 能够生成一份 JSON 或 HTML 报告,比如下图:
lighthouse 可以生成 HTML 和 json 格式的报告,HTML 可以直接打开,json 格式的报告可以通过 https://googlechrome.github.io/lighthouse/viewer/ 这个地址来打开。
3.2 使用Chrome浏览器开发者工具(F12)自带功能
在高版本(应该是 >= 60)的 Chrome 浏览器中,Lighthouse 已经直接集成到了调试工具 DevTools 中了,因此不需要进行任何安装或下载。
按 F12 打开开发者工具,可以看到在 console、security 等选项后面有一个 Audits (安装了lighthouse插件或者是高版本的谷歌浏览器可能显示的是 lighthouse)选项,选择该选项,然后点击 generate report 即可。
3.3 使用npm包lighthouse
通过下载 npm 全局包 lighthouse,我们可以直接在命令行当中使用 lighthouse 来对网站进行性能测评。
首先,需要先安装 Node,需要 Node 8 LTS(8.9) 及以上版本。然后安装全局包 lighthouse:
npm install -g lighthouse
安装完成后我们就可以直接对某一个网站运行 lighthouse 命令了:
lighthouse http://www.baidu.com/
// 默认情况下,会在执行命令的当前目录下生成一个 HTML 文件,直接打开该文件即可查看报告
Lighthouse 命令提供了多个参数,通过参数的配置,能够更灵活地进行测评并输出报告结果。常用的参数有:
lighthouse <url> <options>
lighthouse --help //输入 --help 选项可以查看可用的输入、输出选项
lighthouse http://www.baidu.com --view //直接通过浏览器打开HTML报告
lighthouse http://www.baidu.com --output json //结果以 json 格式文件输出
lighthouse http://www.baidu.com --output json --output-path ./myfile.json //指定结果文件输出的目录
lighthouse https://baidu.com --output html --output-path ./report.html //指定结果文件输出的目录
更多参数可参考 lighthouse的 github 官网:https://github.com/GoogleChrome/lighthouse
3.4 Lighthouse运行的生命周期
Lighthouse 运行测评的过程有一套完整的生命周期,可以划分成三个主要流程:
- Collecting(收集数据):首先是 Collecting 流程,这一步会调用内置的驱动程序(Driver) ,其作用是通过谷歌开发工具协议( Chrome DevTools Protocol) 调起浏览器,并创建新的 tab 请求待测评的站点,通过浏览器采集站点数据并将结果(称之为 Artifacts)保存在本地临时目录。
- Auditing(分析数据):然后进入 Auditing 流程,读取 Artifacts 数据,根据内置的评判策略逐条进行检查并计算出各项的数字形式得分。
- Report(生成报告):最后进行 Report 流程,将评分结果按照 PWA、性能、无障碍访问、最佳实践等纬度进行划分,以 JSON、HTML 等格式输出。
如下图:
命令行工具基于此提供了生命周期的选项,我们可以让 CLI 只运行整个测评过程的一个或多个特定生命周期。比如,使用 --gather-mode(-G)
只进行资源采集的生命周期,命令行工具将会启动浏览器,采集被测试站点的相关数据,并将结果以 json 的形式存储到本地,默认是./latest-run/
目录,然后退出进程:
lighthouse https://example.com/ -G
如果想要跳过浏览器的交互,直接从本地读取页面的临时数据,运行测评和产出结果报告,则可以使用 --audit-mode(-A)
,默认将从./latest-run/
目录读取:
lighthouse https://example.com/ -A
两个选项同时使用,就会运行整个测评的生命周期,与直接运行 lighthouse 命令相比,会在当前目录保存一份测试站点的数据。
lighthouse https://example.com -GA
如果不想使用默认的 ./latest-run/ 目录,我们也能自定义站点的 json 数据的保存目录,如:
lighthouse -GA=./mycustomfolder https://example.com
3.5 Lighthouse报告的指标分析
使用 Lighthouse 对网站进行测评后,我们会得到一份评分报告,它包含了性能(Performance),访问无障碍(Accessibility),最佳实践(Best Practice),搜索引擎优化(SEO),PWA(Progressive Web App)五个部分:
3.5.1 性能(Performance)
性能评分的分值区间是0到100,如果出现0分,通常是在运行 Lighthouse 时发生了错误,满分100分代表了网站已经达到了98分位值的数据,而50分则是75分位值的数据。
3.5.1.1 影响评分的性能指标
影响评分的性能指标:性能测试结果会分成 Metrics,Diagnostic,Opportunities 三部分,通常情况下只有 Metrics 部分的指标项会对分数产生直接影响。
Lighthouse 会衡量以下 Metrics 性能指标项:
- 首次内容绘制(First Contentful Paint)。即浏览器首次将任意内容(如文字、图像、canvas 等)绘制到屏幕上的时间点。
- 首次有效绘制(First Meaningful Paint)。衡量了用户感知页面的主要内容(primary content)可见的时间。对于不同的站点,首要内容是不同的,例如:对于博客文章,标题及首屏文字是首要内容,而对于购物网站来说,图片也会变得很重要。
- 首次 CPU 空闲(First CPU Idle)。即页面首次能够对输入做出反应的时间点,其出现时机往往在首次有效绘制完成之后。该指标目前仍处于实验阶段。
- 可交互时间(Time to Interactive)。指的是所有的页面内容都已经成功加载,且能够快速地对用户的操作做出反应的时间点。该指标目前仍处于实验阶段。
- 速度指标(Speed Index)。衡量了首屏可见内容绘制在屏幕上的速度。在首次加载页面的过程中尽量展现更多的内容,往往能给用户带来更好的体验,所以速度指标的值约小越好。
- 输入延迟估值(Estimated Input Latency)。这个指标衡量了页面对用户输入行为的反应速度,其基准值应低于 50ms。
Metrics 部分的指标项会直接影响分数,可以作为我们的主要参考点。
3.5.1.2 性能指标评分的计算
每一项性能指标对评分的贡献都有其计算逻辑,Lighthouse 会将原始的性能值映射成为 0-100 之间的数字。评分使用 HTTPArchive 上的真实站点性能数据作为样本,统计出对数正态分布。
例如,FMP(First Meaningful Paint)的原始值是从页面初始化开始到主要内容渲染成功的耗时,根据真实站点的数据,顶级性能的站点的 FMP 值约为 1220ms,这个值会被映射成 Lighthouse 的 99 分。
针对不同的评分,Lighthouse 用了不同的颜色进行标注,分值区间和颜色的对应关系如下:
- 0 - 49(慢):红色
- 50 - 89(平均值): 橙色
- 90 - 100(快):绿色
各个指标对性能评分的贡献并不相同,权重较大的指标,对性能评分的影响更大一些。各指标权重分配情况可参考:https://googlechrome.github.io/lighthouse/scorecalc/
3.5.2 访问无障碍(Accessibility)
访问无障碍评分的分值由相关指标的加权平均值计算而来。可以在评分详情查阅每项指标的具体权重。同理,较大权重的指标项对分数的影响较大。
无障碍性的每个指标项测试结果为pass或者fail,与性能指标项的计算方式不同,当页面只是部分通过某项指标时,页面的这项指标将不会得分。例如,如果页面中的一些元素有屏幕阅读器友好的命名,而其他的元素没有,那么这个页面的 screenreader-friendly-names 指标项得分为0。
3.5.3 最佳实践(优化)(Best Practice)
最佳实践评分的分数区间为0-100。影响这项评分的指标项的权重都是相同的。
比如:推荐使用 https,跨域的跳转链接需要使用 rel 标识,不能使用废弃的 API等等。
3.5.4 搜索引擎优化(SEO)
比如:图片元素使用 alt 属性等等提高搜索引擎搜索排名,便于搜索引擎能找到你这个网站。
3.5.5 PWA(Progressive Web App)
Lighthouse 使用 PWA 基准检查项列表(Baseline PWA Checklist)进行测评,测评结果将这些指标项分成了四个类别,共包含12个自动测试项和3个手动测试项,其中各个自动测试项的评分权重是相同的。PWA 的评测指标对我们来说非常重要,我们可以从这四个类别详细了解一下基准指标项。
快速可靠:
- 页面在移动网络条件下能够快速加载
- 在离线条件下页面能够返回状态码200。这里我们可以通过 Service Worker 来实现离线可用
- start_url 在离线条件下返回状态码200。start_url 是manifest.json 中的一个属性,它指定了用户打开该 PWA 时加载的 URL
可安装:
- 始终使用 HTTPS
- 注册 Service Worker 来缓存页面以及 start_url
- 使用 manifest 文件来实现安装 PWA 的需求,浏览器能够主动通知用户将应用添加到桌面,增加留存率
PWA 优化:
- 将 HTTP 流量重定向到 HTTPS
- 配置自定义启动画面
- 设置地址栏主题颜色
- 页面内容针对视口大小自适应,对移动用户的展示更友好
- 使用了
<meta name="viewport">
标签,并设置了 width 或 initial-scale 属性 - 当 JavaScript 文件不可用时,提供降级措施,页面能显示基本内容而不出现白屏
手动测试项:
- 站点跨浏览器可用,如主流浏览器 Chrome, Edge, Firefox 及 Safari 等
- 页面间切换流畅,即使在较差的网络环境下,切换动画也应该简洁顺畅,这是提高用户感知体验的关键
- 保证每个页面都有独一无二的 URL,能够在新的浏览器窗口打开,且方便在社交媒体上进行分享
除了上述基准指标项之外,为了让 PWA 的体验更加完美,还有一些 Lighthouse 未实现检查的进阶指标,也就是可以作为示范性参考的 PWA 的指标,比如用户体验、缓存、推送通知等等。
4、Lighthouse优化
Lighthouse优化总结:
-
减少未使用的 JavaScript
Remove unused JavaScript
请减少未使用的 JavaScript,并等到需要使用时再加载脚本,以减少网络活动耗用的字节数 -
采用新一代格式提供图片
Serve images in modern formats
WebP 和 AVIF 等图片格式的压缩效果通常优于 PNG 或 JPEG,因而下载速度更快,消耗的数据流量更少 -
适当调整图片大小
Properly size images
提供大小合适的图片可节省移动数据网络流量并缩短加载用时 -
推迟加载屏幕外图片
Defer offscreen images
建议您在所有关键资源加载完毕后推迟加载屏幕外图片和处于隐藏状态的图片,从而缩短可交互前的耗时 -
移除阻塞渲染的资源
Eliminate render-blocking resources
资源阻止了系统对您网页的首次渲染。建议以内嵌方式提供关键的 JS/CSS,并推迟提供所有非关键的 JS/样式 -
减少未使用的 CSS
Remove unused CSS
请从样式表中减少未使用的规则,并延迟加载首屏内容未用到的 CSS,以减少网络活动耗用的字节数 -
使用视频格式提供动画内容
Use video formats for animated content
使用大型 GIF 提供动画内容会导致效率低下。建议您改用 MPEG4/WebM 视频(来提供动画)和 PNG/WebP(来提供静态图片)以减少网络活动消耗的字节数 -
预先连接到必要的来源
Preconnect to required origins
建议添加 preconnect 或 dns-prefetch 资源提示,以尽早与重要的第三方来源建立连接 -
应避免向新型浏览器提供旧版JavaScript
Deploying ES2015+ Code in Production Today
Polyfill 和 transform 让旧版浏览器能够使用新的 JavaScript 功能。不过,其中的很多函数对新型浏览器而言并非必需。对于打包的 JavaScript,请采用现代脚本部署策略,以便利用 module/nomodule 功能检测机制来减少传送到新型浏览器的代码量,同时保留对旧版浏览器的支持 -
确保文本在网页字体加载期间保持可见状态
Ensure text remains visible during webfont load
利用 font-display 这项 CSS 功能,确保文本在网页字体加载期间始终对用户可见 -
未使用被动式监听器来提高滚动性能
Use passive listeners to improve scrolling performance
建议您将触摸和滚轮事件监听器标记为 passive,以提高页面的滚动性能,passive不会对事件的默认行为说 no -
图片元素没有明确的width和height
请为图片元素设置明确的宽度值和高度值,以减少布局偏移并改善 CLS -
注册“unload”事件监听器
Legacy lifecycle APIs to avoid
unload事件不会可靠地触发,而且监听该事件可能会妨碍系统实施“往返缓存”之类的浏览器优化策略。建议您改用pagehide或visibilitychange事件 -
最大限度地减少主线程工作
Minimize main thread work
建议您减少为解析、编译和执行 JS 而花费的时间。您可能会发现,提供较小的 JS 负载有助于实现此目标 -
采用高效的缓存策略提供静态资源
Serve static assets with an efficient cache policy
延长缓存期限可加快重访您网页的速度 -
缩短 JavaScript 执行用时
Reduce JavaScript execution time
建议您减少为解析、编译和执行 JS 而花费的时间。您可能会发现,提供较小的 JS 负载有助于实现此目标 -
避免链接关键请求
Avoid chaining critical requests
下面的关键请求链显示了以高优先级加载的资源。请考虑缩短链长、缩减资源的下载文件大小,或者推迟下载不必要的资源,从而提高网页加载速度 -
请保持较低的请求数量和较小的传输大小
Use Lighthouse for performance budgets
performancebudget
若要设置页面资源数量和大小的预算,请添加 budget.json 文件 -
最大内容渲染时间元素
Largest Contentful Paint
这是此视口内渲染的最大内容元素 -
请避免出现大幅度的布局偏移
这些 DOM 元素对该网页的 CLS 影响最大 -
应避免出现长时间运行的主线程任务
Are long JavaScript tasks delaying your Time to Interactive?
列出了主线程中运行时间最长的任务,有助于识别出导致输入延迟的最主要原因 -
避免使用未合成的动画
Avoid non-composited animations
未合成的动画可能会卡顿并增加 CLS -
缩减 CSS
Minify CSS
缩减 CSS 文件大小可缩减网络负载规模 -
缩减 JavaScript
Minify JavaScript
如果缩减 JavaScript 文件大小,则既能缩减负载规模,又能缩短脚本解析用时 -
对图片进行高效编码
Efficiently encode images
如果图片经过了优化,则加载速度会更快,且消耗的移动数据网络流量会更少 -
启用文本压缩
Enable text compression
对于文本资源,应先压缩(gzip、deflate 或 brotli),然后再提供,以最大限度地减少网络活动消耗的字节总数 -
初始服务器响应用时较短
Reduce server response times (TTFB)
请确保服务器响应主文档的用时较短,因为这会影响到所有其他请求的响应时间 -
避免多次网页重定向
Avoid multiple page redirects
重定向会在网页可加载前引入更多延迟 -
预加载关键请求
Preload key requests
建议使用 来优先提取当前在网页加载后期请求的资源 -
使用 HTTP/2
Does not use HTTP/2 for all of its resources
HTTP/2 提供了许多优于 HTTP/1.1 的益处,包括二进制标头和多路复用 -
请移除 JavaScript 软件包中的重复模块
从软件包中移除重复的大型 JavaScript 模块可减少网络传输时不必要的流量消耗 -
预加载 LCP 元素所用图片
优化 Largest Contentful Paint 最大内容绘制
请预加载 Largest Contentful Paint (LCP) 元素所用的图片,以缩短您的 LCP 用时 -
避免网络负载过大
Avoid enormous network payloads
网络负载过大不仅会让用户付出真金白银,还极有可能会延长加载用时 -
避免 DOM 规模过大
Avoid an excessive DOM size
大型 DOM 会增加内存使用量、导致样式计算用时延长,并产生高昂的布局重排成本 -
User Timing 标记和测量结果
User Timing marks and measures
建议使用 User Timing API 检测您的应用,从而衡量应用在关键用户体验中的实际性能 -
尽量减少第三方使用
Loading Third-Party JavaScript
第三方代码可能会显著影响加载性能。请限制冗余第三方提供商的数量,并尝试在页面完成主要加载后再加载第三方代码 -
使用 Facade 延迟加载第三方资源
Lazy load third-party resources with facades
您可以延迟加载某些第三方嵌入代码。不妨考虑使用 Facade 替换这些代码,直到您需要使用它们为止 -
Largest Contentful Paint 所对应的图片未被延迟加载
The performance effects of too much lazy-loading
被延迟加载的首屏图片会在页面生命周期内的较晚时间呈现,这可能会致使系统延迟渲染最大内容元素 -
请勿使用 document.write()
Uses document.write()
对于连接速度较慢的用户,通过 document.write() 动态注入的外部脚本可将网页加载延迟数十秒 -
具有包含 width 或 initial-scale 的 标记
Does not have a tag with width or initial-scale
参考链接:
http://www.alloyteam.com/2020/01/14184/
https://www.cnblogs.com/wenxuehai/p/14236426.html#_label3
lighthouse评分指南:https://lavas-project.github.io/pwa-book/appendix01/2-lighthouse-score-guide.html
lighthouse 的 github 网址:https://github.com/GoogleChrome/lighthouse
PWA和lighthouse的一些使用教程:https://lavas-project.github.io/pwa-book/appendix01/1-lighthouse.html