JS篇之性能优化

很多时候面试官,面试你的时候会问你:同学你在项目中做过哪些性能优化呢?

可能你是这样回答的:

  1. 无用代码的删除,减小代码打的体积
  2. 使用cdn加速
  3. 图片压缩
  4. 分包
  5. 骨架屏

........

其实性能优化是个很宽泛的东西,可以从多方面进行入手

性能优化不是视觉体验打分,网上部分评判如下

核心指标 定义 优化方向
LCP(最大内容绘制) 首屏最大内容加载完成时间 图片压缩、CDN 加速、关键 CSS 内联
FID(首次输入延迟) 用户首次交互到响应的时间 减少主线程长任务、Web Worker 拆分计算
CLS(累积布局偏移) 页面元素意外偏移的累积分数 图片 / 视频设置固定尺寸、避免动态插入内容

上面说的三种指标跟首屏渲染和白屏渲染又有啥关系呢?

上面三种指标是因,而白屏和首屏是果

LCP(Largest Contentful Paint,最大内容绘制)是 Core Web Vitals(核心网页指标)中最重要的加载性能指标,它衡量的是页面加载过程中,最大的内容元素在视口中完成绘制的时间,直接反映用户对 "页面主要内容是否加载完成" 的感知。

什么元素会被算作 "最大内容"?

LCP 通常关注以下类型的元素(取其中尺寸最大的那个):

  • <img> 标签(包括 srcsetpicture 中的图片)
  • <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

    javascript 复制代码
    import { 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 时间过长通常与资源加载、服务器响应、渲染阻塞等问题相关:

  1. 服务器响应延迟(TTFB 过长)

    • 服务器处理请求速度慢(如负载过高、代码逻辑低效),导致页面 "首次字节" 到达浏览器的时间过长,直接推迟内容绘制。
  2. 阻塞性资源加载缓慢

    • 关键 CSS 未优化:外部 CSS 文件过大或加载延迟,浏览器需等待 CSS 解析完成才能渲染内容(CSS 会阻塞渲染)。
    • 阻塞性 JavaScript:未使用async/defer的 JS 文件会阻塞 HTML 解析,若加载或执行缓慢,会延迟 DOM 构建和内容绘制。
  3. 网络环境差

    • 网络速度慢、不稳定,或资源未使用 CDN 分发,导致关键资源(如 HTML、CSS、首屏图片)加载耗时增加。
  4. 页面渲染准备不足

    • 首屏内容依赖异步数据加载(如 API 请求延迟),导致内容无法及时生成。
    • 复杂的 DOM 结构或样式计算,增加浏览器渲染首屏内容的时间。

如何优化 FCP?

  1. 减少服务器响应时间(TTFB)

    • 优化服务器配置(如使用缓存、升级硬件)、减少数据库查询耗时、采用 CDN 分发静态资源。
  2. 优化关键资源加载

    • 内联关键 CSS:将首屏必需的 CSS 直接嵌入 HTML(避免外部 CSS 文件加载延迟阻塞渲染),非关键 CSS 异步加载。
    • 控制阻塞性 JS :对非首屏必需的 JS 使用async(异步加载,加载完成后立即执行)或defer(延迟到 HTML 解析完成后执行),避免阻塞 DOM 解析。
  3. 提升网络加载效率

    • 压缩资源(HTML/CSS/JS 压缩、图片压缩与格式优化,如使用 WebP),减少文件体积。
    • 预加载关键资源:通过<link rel="preload">提前加载首屏必需的资源(如字体、关键图片)。
  4. 优化首屏内容渲染

    • 优先加载首屏内容,延迟加载非首屏内容(如 "懒加载" 图片)。
    • 避免首屏内容依赖异步数据:可先渲染静态骨架屏或占位内容,待数据加载完成后替换。
  5. 简化 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 的延迟主要源于浏览器的 "主线程阻塞",即主线程被耗时任务占用,无法及时处理用户输入:

  1. JavaScript 执行时间过长

    • 大型 JavaScript 文件未优化(如未压缩、未拆分),导致解析、编译和执行时间过长;
    • 同步执行的长任务(如复杂计算、循环)阻塞主线程。
  2. 布局与渲染阻塞

    • 频繁的 DOM 操作(如大量元素添加 / 删除)导致浏览器频繁重排(Reflow)或重绘(Repaint);
    • 复杂的 CSS 选择器或动画计算占用主线程资源。
  3. 资源加载时机不当

    • 非关键 JavaScript 在页面加载初期就加载并执行,抢占主线程资源。

如何优化 FID?

  1. 优化 JavaScript 执行

    • 拆分大型 JS 文件,采用代码分割(Code Splitting),优先加载关键 JS,非关键 JS 延迟加载;
    • 使用requestIdleCallback将非紧急任务推迟到浏览器空闲时执行;
    • 避免同步长任务,将复杂计算放入 Web Worker(不阻塞主线程)。
  2. 减少主线程阻塞

    • 压缩和最小化 JS/CSS 文件,减少加载和解析时间;
    • 优化 DOM 结构,减少不必要的元素和嵌套,避免频繁重排 / 重绘。
  3. 合理控制资源加载

    • 对非关键资源使用asyncdefer属性加载,避免阻塞 HTML 解析;
    • 预加载关键资源(如使用<link rel="preload">),但避免过度预加载导致资源浪费。

如何检测 FID?

  • Lighthouse:在性能分析报告中可查看 FID 数值及优化建议;

  • Chrome DevTools:通过 "Performance" 面板录制页面交互过程,分析主线程阻塞情况;

  • Web Vitals API :通过代码实时监测并上报 FID 数据(如使用web-vitals库)。

通过优化 FID,能显著提升用户与页面交互时的流畅度,尤其对交互密集型页面(如表单、后台系统、电商页面)至关重要。

总结

常见的指标有这么多,但是性能优化的方式是宽广的,你讲配置,讲网络优化 讲css渲染 讲js结构化,讲,讲异步的动画帧优化。。。。反正这些都能给页面提速的,在实际项目中还是要针对某一问题做专项优化安排。

相关推荐
程序员海军12 小时前
2025年上半年前端技术圈生态总结分享
前端·vue.js·react.js
记忆怪 bug12 小时前
2025前端面试题及答案(详细)
前端
群联云防护小杜12 小时前
服务器异常负载排查手册 · 隐蔽进程篇
运维·服务器·前端·数据库·笔记·sql·tcp/ip
小小菜鸡ing13 小时前
简单爬一个小说页面 HTML 的title和内容
前端·html
IT_陈寒13 小时前
Spring Boot 3 + GraalVM:5个实战技巧让Java应用启动速度提升300%
前端·人工智能·后端
前端世界13 小时前
前端跨域终极指南:3 种优雅解决方案 + 可运行 Demo
前端·javascript·状态模式
无奈何杨13 小时前
CoolGuard风控系统配置评分卡、权重策略|QLExpress脚本
前端·后端
几度风雨见丹心13 小时前
vue+elementUI 进行表格行内新增及校验,同行其他输入框数据影响当前输入框校验结果
前端·vue.js·elementui
开发者小天13 小时前
在Ant Design Vue 中使用图片预览的插件
前端·javascript·vue.js·前端框架
华科云商xiao徐13 小时前
手把手教你用Go打造带可视化的网络爬虫
前端·爬虫