导读
在现代 Web 开发中,前端性能优化变得越来越重要。良好的性能不仅提升用户体验,还能显著提高应用的用户留存率和转化率。在这篇文章中,将介绍前端性能优化的一些指导性的原则,性能优化的关键性能指标和一些常见的优化手段。
Web 性能指标
提及前端性能优化,我们首先需要了解Web 性能指标(Web Vitals)的概念,也就是我们首先需要知道到底要优化哪些数据指标。
Core Web Vitals
Core Web Vitals 是 Google 提出的用来衡量和优化网页用户体验的一组关键性能指标。这些指标旨在反映一个网站的实际用户体验,包括加载性能、交互性和视觉稳定性。优化这些指标不仅可以提升用户的满意度和参与度,还能影响网站在搜索引擎中的排名。
Core Web Vitals 目前包括以下三个主要指标:
- Largest Contentful Paint (LCP):最大内容绘制,测量加载性能。为了提供良好的用户体验,LCP 应在页面首次开始加载后的2.5 秒内发生。
- First Input Delay (FID):首次输入延迟,测量交互性。为了提供良好的用户体验,页面的 FID 应为100 毫秒或更短。
- Cumulative Layout Shift (CLS):累积布局偏移,测量视觉稳定性。为了提供良好的用户体验,页面的 CLS 应保持在 0.1 或更少。
核心性能指标的阈值
其它重要 Web 性能指标
除了 Core Web Vitals 中的三个核心性能指标外,还有3个需要了解的重要 Web 性能指标:
Total Block Time(TBT)
Total Block Time(TBT) :总阻塞时间,测量加载相应速度的重要实验室指标。测量First Contentful Paint 首次内容绘制 (FCP)与Time to Interactive 可交互时间 (TTI)之间的总时间,这期间,主线程被阻塞的时间过长,无法作出输入响应。该项指标有助于量化在页面交互性变为可靠前,不可交互程度的严重性,较低的 TBT 有助于确保页面的可用性。
Time to Interactive (TTI)
Time to Interactive (TTI) :可交互时间,测量加载响应度的重要实验室指标。测量页面从开始加载到主要子资源完成渲染,并能够快速、可靠地响应用户输入所需的时间。该指标有助于识别看起来具备交互性但实际上并非如此的页面情况。迅捷的 TTI 有助于确保页面的有效性。
Speed Index(SI)
Speed Index(SI) :速度索引,是一个非核心Web重要指标。用于衡量页面加载过程中页面内容的可视填充速度。它是使用页面加载行为的逐帧分析计算的,计算每100毫秒捕获的帧之间的视觉进度。
其它 Web 性能指标的阈值
性能优化原则(Principles of Optimization)
我接触到的最早的前端性能优化原则是 Steve Souders 在他 2008 年出版的《高性能网站建设指南》一书中介绍的 14 条优化原则:
- 减少 HTTP 请求
- 使用内容发布网络
- 添加 Expires 头
- 压缩组件
- 将样式表放在顶部
- 将脚本放在底部
- 避免 CSS 表达式
- 使用外部 JavaScript 和 CSS
- 坚守 DNS 查找
- 精简 JavaScript
- 避免重定向
- 移除重复脚本
- 配置 ETag
- 使 Ajax 可缓存
接着 2010 年他又联合其他几位大咖编写出版了《高性能网站建设进阶指南》,又给出很多其它的优化原则:
- 拆分初始化负载
- 整合异步脚本
- 布置行内脚本
- 编写高效的 JavaScript
- 可伸缩的 Comet
- 图像优化
- 划分主域名
- 尽早刷新文档的输出
- 减少 iframe
- 简化 CSS 选择符
(PS:如果还有不太了解这些优化原则细节的同学,推荐一定下载电子书或者购买纸质的书去阅读一下。)
性能优化最佳实践(Best Practices)
上图很清晰的显出了 Web 页面实际的渲染效果,也很直观的显出各个 Web 性能指标针对性能优化的各个不同阶段。
其实在浏览器正式显示 Web 页面内容之前,浏览器还做了一些其它的事情。
而针对 HTTP 请求阶段,也是可以针对性的进行一些性能优化措施的。
性能优化是一个系统性的工程,所以作为前端工程师需要了解浏览器从发起 HTTP 请求,到解析静态资源和绘制 UI 界面的整个过程的处理机制。
OK,下面就介绍一下针对加载速度、渲染性能和运行时解析脚本的常见的性能优化最佳实践:
优化加载速度
加载速度是前端性能优化的基础,影响用户对应用的第一印象。以下是一些关键的优化策略:
- 减少 HTTP 请求: 每一个 HTTP 请求都会增加页面加载时间。可以通过合并 CSS 和 JavaScript 文件、使用图像精灵(Sprite)、内联小型资源等方式减少请求数量。
- 使用内容分发网络(CDN) : CDN 可以将资源分发到距离用户最近的服务器上,减少加载时间。
- 启用压缩: 使用 Gzip 或 Brotli 等压缩技术可以显著减少文件大小,加快加载速度。确保服务器配置正确,支持对文本文件(如 HTML、CSS、JavaScript)进行压缩。
- 缓存资源: 利用浏览器缓存机制可以避免重复下载相同的资源。设置合适的
Cache-Control和ETag响应头,以确保静态资源被合理缓存。 - 优化图像: 图像通常是网页中最大的资源,优化图像能够显著减少加载时间。可以使用现代图像格式(如 WebP),调整图像的质量和尺寸,删除不必要的元数据,使用延迟加载(lazy loading)技术来提高性能。
- 减少重定向: 重定向会增加额外的 HTTP 请求和延迟,应尽量减少使用。
优化渲染性能
渲染性能直接影响页面的交互性和响应速度。以下是一些优化渲染性能的建议:
- 避免阻塞渲染的 CSS 和 JavaScript: 在页面加载时,浏览器会阻塞渲染,直到关键资源被加载和解析。将关键的 CSS 放在
<head>中,而将非关键的 CSS 通过media属性进行延迟加载。对于 JavaScript,尽量放在页面底部或使用async、defer属性。 - 减少 DOM 操作: 频繁的 DOM 操作会降低页面性能,尤其是在复杂的页面中。尽量减少直接的 DOM 操作,使用文档片段(Document Fragment)来批量更新 DOM 或者使用虚拟 DOM 技术(如 React、Vue)来优化更新。
- 使用 CSS 动画和硬件加速: 相比 JavaScript 动画,CSS 动画通常更高效,因为它们可以由浏览器的合成层来执行,从而利用硬件加速。尝试使用
transform和opacity属性进行动画,这些属性不会触发布局和重绘。 - 优化字体加载: 自定义字体通常会增加页面加载时间。使用
font-displayCSS 属性设置字体加载策略,比如swap或fallback,以减少字体加载对渲染的阻塞。
优化运行时性能
运行时性能优化主要关注 JavaScript 的执行效率和内存使用。以下是一些常见的优化策略:
- 减少 JavaScript 负载: 移除不必要的 JavaScript 代码和依赖,采用懒加载(lazy loading)策略按需加载模块。使用工具(如 Webpack、Rollup)进行代码分割和按需加载,避免一次性加载过多的代码。
- 优化 JavaScript 执行: 避免使用性能较差的 JavaScript 代码,如长时间运行的循环和复杂的计算。将重计算和高开销的操作推迟到不影响用户体验的时机,或者使用 Web Workers 将复杂的计算放到后台线程中执行。
- 避免内存泄漏: 内存泄漏会导致性能问题和应用崩溃。避免在代码中创建无法被垃圾回收的引用,如全局变量和事件监听器,及时清理不再使用的 DOM 元素和事件监听。
关注移动端优化
移动端设备的硬件和网络环境通常比桌面端更有限,因此对移动端进行优化尤为重要:
- 响应式设计: 使用响应式设计(Responsive Design)确保应用在各种设备和屏幕尺寸上都能正常显示和操作。
- 减少移动端数据传输量: 尽量减少移动端页面的资源大小和请求数,避免高数据消耗。
- 优化触摸事件: 确保页面响应迅速,避免过多的触摸事件监听器和复杂的触摸操作逻辑。
性能分析工具
利用性能分析工具可以帮助开发者识别和解决性能瓶颈。以下是一些常用的工具:
- Google Chrome DevTools: Chrome 开发者工具提供了丰富的性能分析功能,包括性能面板(Performance Panel)、网络面板(Network Panel)和内存面板(Memory Panel),可以帮助分析加载速度、渲染性能和内存使用情况。
- Lighthouse: Lighthouse 是一个自动化的开源工具,能够分析 Web 应用的性能、可访问性、SEO 等多个方面。它提供了详细的性能报告和优化建议。
- WebPageTest: WebPageTest 是一个在线性能测试工具,可以模拟不同的网络环境和设备,生成详细的性能报告,包括加载时间、资源大小和请求数等。
使用 Web Vitals API 在 JavaScript 中测量核心性能指标
除了前文介绍的性能分析工具外,要测量这些性能指标指标,还可以使用 web-vitals JavaScript 库,通过 web-vitals 库,开发者可以轻松地测量和收集 Web Vitals 性能指标。这些数据可以帮助识别和优化网页性能,改善用户体验。对于生产环境,可以将这些数据发送到分析工具或服务器,进行更详细的分析和监控。
安装 web-vitals 库
npm install web-vitals
使用 web-vitals 库来测量核心性能指标
安装完成后,可以在你的 JavaScript 文件中导入和使用它来测量这些指标。
import { getCLS, getFID, getLCP, getFCP, getTTFB } from 'web-vitals';
function sendToAnalytics(metric) {
// 将性能指标发送到你的分析服务
console.log(metric);
}
// 测量 CLS(累计布局偏移)
getCLS(sendToAnalytics);
// 测量 FID(首次输入延迟)
getFID(sendToAnalytics);
// 测量 LCP(最大内容绘制)
getLCP(sendToAnalytics);
// 可选:测量其他 Web Vitals 指标
getFCP(sendToAnalytics); // 首次内容绘制
getTTFB(sendToAnalytics); // 首字节时间
API 方法简介
getCLS(callback): 测量 CLS 指标并在指标可用时调用callback函数。CLS 衡量页面的布局稳定性,较高的值意味着布局发生了较大的变化,影响用户体验。getFID(callback): 测量 FID 指标并在指标可用时调用callback函数。FID 衡量用户首次与页面交互(例如点击链接、按钮等)到页面实际响应的时间。getLCP(callback): 测量 LCP 指标并在指标可用时调用callback函数。LCP 衡量页面主内容加载的时间,这一指标越低,用户感知到的速度就越快。getFCP(callback): 可选的函数,用于测量 FCP(首次内容绘制),即浏览器首次绘制 DOM 内容的时间。getTTFB(callback): 可选的函数,用于测量 TTFB(首字节时间),即从客户端请求页面到浏览器接收第一个字节数据的时间。
自定义指标收集
你可以将这些指标数据发送到自己的分析服务器以进行更详细的分析。下面是一个示例,将指标发送到自定义服务器:
function sendToAnalytics(metric) {
const body = JSON.stringify(metric);
const url = 'https://your-analytics-endpoint.com/vitals';
// 使用 navigator.sendBeacon 发送数据,不阻塞页面卸载
if (navigator.sendBeacon) {
navigator.sendBeacon(url, body);
} else {
fetch(url, {
body,
method: 'POST',
keepalive: true
});
}
}
总结
前端性能优化是一个复杂而持续的过程,需要开发者在不同层面上进行优化和调整。通过优化加载速度、渲染性能和运行时性能,以及使用性能分析工具和关注移动端优化,开发者可以显著提升 Web 应用的性能和用户体验。保持对新技术和最佳实践的关注,不断优化和改进,是打造高性能 Web 应用的关键。