很多时候面试官,面试你的时候会问你:同学你在项目中做过哪些性能优化呢?
可能你是这样回答的:
- 无用代码的删除,减小代码打的体积
- 使用cdn加速
- 图片压缩
- 分包
- 骨架屏
........
其实性能优化是个很宽泛的东西,可以从多方面进行入手
性能优化不是视觉体验打分,网上部分评判如下
核心指标 | 定义 | 优化方向 |
---|---|---|
LCP(最大内容绘制) | 首屏最大内容加载完成时间 | 图片压缩、CDN 加速、关键 CSS 内联 |
FID(首次输入延迟) | 用户首次交互到响应的时间 | 减少主线程长任务、Web Worker 拆分计算 |
CLS(累积布局偏移) | 页面元素意外偏移的累积分数 | 图片 / 视频设置固定尺寸、避免动态插入内容 |
上面说的三种指标跟首屏渲染和白屏渲染又有啥关系呢?
上面三种指标是因,而白屏和首屏是果
LCP(Largest Contentful Paint,最大内容绘制)是 Core Web Vitals(核心网页指标)中最重要的加载性能指标,它衡量的是页面加载过程中,最大的内容元素在视口中完成绘制的时间,直接反映用户对 "页面主要内容是否加载完成" 的感知。
什么元素会被算作 "最大内容"?
LCP 通常关注以下类型的元素(取其中尺寸最大的那个):
<img>
标签(包括srcset
和picture
中的图片)<svg>
中的<image>
元素- 带
poster
属性的<video>
标签(poster 图会被视为内容) - 通过
url()
加载背景图的元素(仅当背景图通过 CSS 加载且是页面主要内容时) - 块级元素中的文本节点(如
<h1>
、<p>
中的大段文本)
LCP 的评分标准
- 良好:≤ 2.5 秒(用户会觉得 "加载很快")
- 需要改进:2.5 秒~4 秒
- 差:> 4 秒(用户会明显感觉 "加载缓慢")
影响 LCP 的常见原因及优化手段
LCP 慢的核心原因是最大内容元素加载 / 渲染延迟,优化需围绕 "让最大内容更快呈现" 展开:
1. 优化图片 / 视频等资源(最常见场景)
-
选择合适的图片格式:优先使用 WebP、AVIF 等现代格式(比 JPG/PNG 小 20%-50%)。
-
图片压缩与尺寸适配 :通过工具(如 Sharp、Squoosh)压缩图片,并用
srcset
+sizes
提供不同尺寸,避免加载过大图片(如移动端加载桌面端大图)。html
ini<img src="small.jpg" srcset="small.jpg 400w, medium.jpg 800w, large.jpg 1200w" sizes="(max-width: 600px) 400px, (max-width: 1200px) 800px, 1200px" alt="示例图片" >
-
预加载关键图片 :对 LCP 候选图片(如首屏主图)用
<link rel="preload">
提前加载:html
ini<link rel="preload" as="image" href="hero.jpg" fetchpriority="high">
-
懒加载非首屏图片 :避免非首屏图片抢占带宽,但LCP 图片不能懒加载(会延迟绘制)。
2. 优化服务器响应速度(TTFB)
LCP 元素的加载依赖服务器响应,TTFB(首字节时间)过长会直接拖慢 LCP:
- 使用 CDN:将静态资源(图片、JS/CSS)部署到 CDN,缩短用户与资源的物理距离。
- 优化后端接口:减少数据库查询、使用缓存(如 Redis),降低服务器处理时间,目标 TTFB < 600ms。
- 启用 HTTP/2 或 HTTP/3:多路复用减少请求阻塞,加速资源并行加载。
3. 减少渲染阻塞
-
内联关键 CSS :将首屏渲染必需的 CSS 内联到
<head>
中,避免外部 CSS 文件加载阻塞渲染。 -
延迟加载非关键 JS/CSS :用
async
/defer
加载非首屏 JS,用media="print"
标记非首屏 CSS(加载但不阻塞)。html
预览
ini<script src="non-critical.js" defer></script> <link rel="stylesheet" href="print.css" media="print" onload="this.media='all'">
4. 避免布局偏移影响 LCP 计算
如果 LCP 元素因动态样式(如未设置宽高的图片加载后撑开布局)发生位置变化,浏览器可能会重新计算 LCP 时间,导致指标变差。解决方法:
- 为图片 / 视频设置明确的宽高属性(或通过 CSS 预设尺寸),避免布局偏移。
- 使用骨架屏占位,确保 LCP 元素位置提前预留。
如何监测 LCP?
-
Chrome DevTools:在 "Performance" 面板录制页面加载,可看到 LCP 标记和时间。
-
Lighthouse:生成性能报告,直接显示 LCP 得分和具体元素。
-
真实用户监测(RUM) :通过
web-vitals
库在生产环境收集真实用户的 LCP 数据:javascript
javascriptimport { getLCP } from 'web-vitals'; getLCP(metric => { console.log('LCP 时间:', metric.value); // 单位:毫秒 console.log('LCP 元素:', metric.attribution.element); });
FCP
FCP(First Contentful Paint,首次内容绘制)是衡量网页加载性能 的核心指标之一,它记录了浏览器从开始加载页面到首次绘制出任何可见内容(如文本、图像、SVG、非白色背景的元素等)的时间。FCP 直接反映了用户对页面 "是否开始加载" 的第一感知,是评估页面加载体验的关键指标。
FCP 的核心意义
FCP 标志着页面加载的 "第一个里程碑"------ 用户从看到空白屏幕到首次看到实际内容的时间。例如:
- 页面加载时,首个文字段落、图标或背景色块出现的瞬间,即为 FCP 完成的时间点。
- 即使此时页面未完全加载,FCP 的快慢也会直接影响用户对网站速度的第一印象(如 "这个网站加载好慢" 或 "很快就有内容了")。
正常的 FCP 数值范围
根据 Web Vitals(谷歌核心网页性能指标)标准:
- 良好(Good) :FCP ≤ 1.8 秒(用户几乎不会感知到延迟);
- 需要改进(Needs Improvement) :1.8 秒 < FCP ≤ 3 秒(用户可能察觉到轻微延迟);
- 较差(Poor) :FCP > 3 秒(用户明显感觉页面加载缓慢,可能失去耐心)。
FCP 延迟的常见原因
FCP 时间过长通常与资源加载、服务器响应、渲染阻塞等问题相关:
-
服务器响应延迟(TTFB 过长) :
- 服务器处理请求速度慢(如负载过高、代码逻辑低效),导致页面 "首次字节" 到达浏览器的时间过长,直接推迟内容绘制。
-
阻塞性资源加载缓慢:
- 关键 CSS 未优化:外部 CSS 文件过大或加载延迟,浏览器需等待 CSS 解析完成才能渲染内容(CSS 会阻塞渲染)。
- 阻塞性 JavaScript:未使用
async
/defer
的 JS 文件会阻塞 HTML 解析,若加载或执行缓慢,会延迟 DOM 构建和内容绘制。
-
网络环境差:
- 网络速度慢、不稳定,或资源未使用 CDN 分发,导致关键资源(如 HTML、CSS、首屏图片)加载耗时增加。
-
页面渲染准备不足:
- 首屏内容依赖异步数据加载(如 API 请求延迟),导致内容无法及时生成。
- 复杂的 DOM 结构或样式计算,增加浏览器渲染首屏内容的时间。
如何优化 FCP?
-
减少服务器响应时间(TTFB) :
- 优化服务器配置(如使用缓存、升级硬件)、减少数据库查询耗时、采用 CDN 分发静态资源。
-
优化关键资源加载:
- 内联关键 CSS:将首屏必需的 CSS 直接嵌入 HTML(避免外部 CSS 文件加载延迟阻塞渲染),非关键 CSS 异步加载。
- 控制阻塞性 JS :对非首屏必需的 JS 使用
async
(异步加载,加载完成后立即执行)或defer
(延迟到 HTML 解析完成后执行),避免阻塞 DOM 解析。
-
提升网络加载效率:
- 压缩资源(HTML/CSS/JS 压缩、图片压缩与格式优化,如使用 WebP),减少文件体积。
- 预加载关键资源:通过
<link rel="preload">
提前加载首屏必需的资源(如字体、关键图片)。
-
优化首屏内容渲染:
- 优先加载首屏内容,延迟加载非首屏内容(如 "懒加载" 图片)。
- 避免首屏内容依赖异步数据:可先渲染静态骨架屏或占位内容,待数据加载完成后替换。
-
简化 DOM 与样式:
- 减少首屏 DOM 元素数量,避免不必要的嵌套;简化 CSS 选择器,降低浏览器样式计算复杂度。
如何检测 FCP?
-
Lighthouse:在性能报告中直接查看 FCP 数值及具体优化建议(如 "减少未使用的 CSS""优化服务器响应时间")。
-
Chrome DevTools:通过 "Performance" 面板录制页面加载过程,在 "Timings" 中找到 "First Contentful Paint" 时间点。
-
Web Vitals API :通过代码实时监测 FCP(如使用
web-vitals
库),便于线上性能监控。
优化 FCP 能显著提升用户对页面加载速度的第一印象,尤其对内容型网站(如博客、新闻、电商首页)至关重要。
FID
FID(First Input Delay,首次输入延迟)是衡量网页交互响应速度的核心指标之一,主要反映用户首次与页面交互(如点击按钮、输入文字、触摸屏幕等)到浏览器开始处理该交互请求之间的延迟时间。它直接关系到用户对页面 "流畅度" 的感知,是评估网页可用性的重要标准。
FID 的核心意义
用户在页面加载过程中或加载完成后进行交互时,浏览器可能正忙于解析 JavaScript、处理布局计算等任务,导致无法立即响应操作,这种延迟就是 FID。例如:
-
点击按钮后,按钮没有立即反馈(如变色、跳转);
-
在输入框打字时,文字出现卡顿或延迟显示。
FID 值越小,说明页面对用户操作的响应越及时,用户体验越好。
正常的 FID 数值范围
根据 Web Vitals(谷歌提出的核心网页性能指标)标准:
- 良好(Good) :FID ≤ 100 毫秒(用户几乎感觉不到延迟);
- 需要改进(Needs Improvement) :100 毫秒 < FID ≤ 300 毫秒(用户可能察觉到轻微延迟);
- 较差(Poor) :FID > 300 毫秒(用户明显感受到卡顿,影响操作体验)。
FID 延迟的常见原因
FID 的延迟主要源于浏览器的 "主线程阻塞",即主线程被耗时任务占用,无法及时处理用户输入:
-
JavaScript 执行时间过长:
- 大型 JavaScript 文件未优化(如未压缩、未拆分),导致解析、编译和执行时间过长;
- 同步执行的长任务(如复杂计算、循环)阻塞主线程。
-
布局与渲染阻塞:
- 频繁的 DOM 操作(如大量元素添加 / 删除)导致浏览器频繁重排(Reflow)或重绘(Repaint);
- 复杂的 CSS 选择器或动画计算占用主线程资源。
-
资源加载时机不当:
- 非关键 JavaScript 在页面加载初期就加载并执行,抢占主线程资源。
如何优化 FID?
-
优化 JavaScript 执行:
- 拆分大型 JS 文件,采用代码分割(Code Splitting),优先加载关键 JS,非关键 JS 延迟加载;
- 使用
requestIdleCallback
将非紧急任务推迟到浏览器空闲时执行; - 避免同步长任务,将复杂计算放入 Web Worker(不阻塞主线程)。
-
减少主线程阻塞:
- 压缩和最小化 JS/CSS 文件,减少加载和解析时间;
- 优化 DOM 结构,减少不必要的元素和嵌套,避免频繁重排 / 重绘。
-
合理控制资源加载:
- 对非关键资源使用
async
或defer
属性加载,避免阻塞 HTML 解析; - 预加载关键资源(如使用
<link rel="preload">
),但避免过度预加载导致资源浪费。
- 对非关键资源使用
如何检测 FID?
-
Lighthouse:在性能分析报告中可查看 FID 数值及优化建议;
-
Chrome DevTools:通过 "Performance" 面板录制页面交互过程,分析主线程阻塞情况;
-
Web Vitals API :通过代码实时监测并上报 FID 数据(如使用
web-vitals
库)。
通过优化 FID,能显著提升用户与页面交互时的流畅度,尤其对交互密集型页面(如表单、后台系统、电商页面)至关重要。
总结
常见的指标有这么多,但是性能优化的方式是宽广的,你讲配置,讲网络优化 讲css渲染 讲js结构化,讲,讲异步的动画帧优化。。。。反正这些都能给页面提速的,在实际项目中还是要针对某一问题做专项优化安排。