实践指南-前端性能提升 270%

2023-11-13

一、背景

当我们疲于开发一个接一个的需求时,很容易忘记去关注网站的性能,到了某一个节点,猛地发现,随着越来越多代码的堆积,网站变得越来越慢。

本文就是从这样的一个背景出发,着手优化网站的前端性能,并总结出一套开发习惯,让我们在日常开发时,也保持高性能,而不是又一次回过头来优化性能。

指标名称 优化前 优化后 提升
Lighthouse Performance 评分 29 81 279%
FCP(First Contentful Paint 首次内容绘制) 0.7s 0.7s
LCP(Largest Contentful Paint 最大内容绘制) 6.2s 2.5s 248%
TTI(Time to Interactive 可交互时间) 10.1s 2.1s 480%
Speed Index(速度指数) 5.6s 1.8 311%
TBT(Total Blocking Time 总阻塞时间) 820ms 120ms 683%

优化前后对比:

优化前后对比

二、优化前

接下来就是介绍下优化前我们要做哪些事件:

  1. 了解性能指标及测量工具

  2. 分析需要优化的地方

1. 了解测量工具及性能指标

一开始我们只是感受到网站的页面打开时白屏时间较长,感觉性能是比较差的,那么具体有哪些性能指标需要去关注呢?

这里我使用的是 Chrome devtools 内置的Lighthouse,Lighthouse 是一种开源的自动化工具,用于提高 Web 应用程序的质量。

Lighthouse 会在一系列的测试下运行网页,比如不同尺寸的设备和不同的网络速度。它还会检查页面对辅助功能指南的一致性,例如颜色对比度和 ARIA 最佳实践。

打开 Chrome devtools Lighthouse 即可使用。

在比较短的时间内,Lighthouse 可以给出这样一份报告。

这份报告从 5 个方面来分析页面: 性能、辅助功能、最佳实践、搜索引擎优化和 PWA。像性能方面,会给出一些常见的耗时统计。

优化前

1.1 Performance

Performance 评分统计,包括了以下指标:

1.1.1 FCP

FCP 测量在用户导航到页面后浏览器呈现第一段 DOM 内容所花费的时间。页面上的图像、非白色<canvas>元素和 SVG 被视为 DOM 内容;不包括 iframe 内的任何内容。

1.1.2 LCP

LCP 测量视口中最大的内容元素何时呈现到屏幕上。这近似于页面的主要内容对用户可见的时间。

需要注意的是 LCP 的计算是一个动态的过程,如下图最后的图片才是这个页面中的最大内容绘制的元素。

lcp

1.1.3 TTI

TTI 测量页面完全交互所需的时间。

TTI 是如何计算的呢,如下图首先延时间轴正向搜索时长至少为 5 秒的安静窗口(安静窗口是指没有长任务且不超过两个正在处理的网络 get 请求),然后沿时间轴反向搜索安静窗口之前的最后一个长任务,如果没有找到长任务,则在 FCP 步骤停止执行,TTI 就是安静窗口之前最后一个长任务的结束时间,如果没有找到长任务的话,则与 FCP 值相同。

TTI

1.1.4 Speed Index

Speed Index 衡量页面加载期间内容以视觉方式显示的速度。Lighthouse 首先捕获浏览器中页面加载的视频,并计算帧之间的视觉进度。

1.1.5 TBT

TBT 测量页面被阻止响应用户输入(例如鼠标点击、屏幕点击或键盘按下)的总时间。

通过添加 First Contentful Paint 和 Time to Interactive 之间所有长任务的阻塞部分来计算总和。任何执行时间超过 50 毫秒的任务都是长任务。

50 毫秒后的时间量是阻塞部分。例如,如果 Lighthouse 检测到一个 70 毫秒长的任务,则阻塞部分将为 20 毫秒。

如下图淡红色区域的时间总和就是这个页面的 TBT 分数。

TBT

1.2 最佳实践

用于检测 Web 应用程序整体代码健康状况,包括是否包含文档类型、图片宽高比是否正确等等。

1.3 SEO

用于检测搜索引擎对网页内容的理解程度。

2. 分析需要优化的地方

了解了关键的性能指标后,就可以测量看看当前网站的性能了,

上面看到综合评分是非常低的,Lighthouse 给出了应该从哪些地方开始优化的建议。

2.1 Performance

性能优化建议主要包括以下几点:

  • 减少未使用的 JS;

  • 合理使用图片的格式,webp 或者 avif 更快;

  • 延迟加载不在视图的图片;

  • JS 压缩;

  • 图片的尺寸大小应该适当;

  • 减少未使用的 CSS。

性能优化建议

Lighthouse 诊断出的网站存在的问题:

  • 需要加载的资源太多太大,有 147 个请求,合计 11mb;

  • 有 40 个静态资源的缓存只有 1 小时

  • 滚动事件没有添加标记{passive: true}),导致需要等待侦听器完成执行后再滚动页面;

  • 图像元素没有设置明确的宽度和高度;

  • JS 文件太多,主线程工作量太大、JS 执行时间太长;

存在的问题

2.2 最佳实践

最佳实践方面有以下问题:

  • 图片的分辨率太低,清晰度不够;

  • 没有设置 CSP 策略。

最佳实践的问题

2.3 SEO

SEO 有以下问题:

  • 没有 meta description;

  • 图片没有 alt 属性;

  • robots.txt 是无效的。

SEO的问题

三、优化 Performance

根据上面 Lighthouse 报告,捋一捋项目中影响性能最大的因素,包括以下几点:

  • 体积太大,达 11mb;

  • 图片太大,图片格式也有影响。

1. 体积优化

1.1 代码压缩

检查是否还有压缩空间,或者有无工具库未压缩的。

1.2 代码分包

通过 webpack-bundle-analyzer 插件分析包体积,将一些大的 npm 包和 runtimeChunk 独立分包,减小包体积。

1.3 组件按需加载

React.lazy + Suspense 封装懒加载组件,路由级组件引入懒加载组件。
同时使用骨架屏作为懒加载的兜底组件,可以让用户感知加载更快。
在鼠标移入导航栏时预加载路由组件,可以加快页面展示。

1.4 工具库按需加载

通过 import(‘xx’).then(xx) 按需加载工具库。

1.5 静态资源上传 CDN

项目内有一些 json 文件存储的静态数据,这部分文件上传至 CDN,改为 fetch 的方式按需引入。

1.6 删除不需要的资源

检查项目中引入的 mf、npm 资源,将没有使用到的删除。

1.7 避免重复的 npm 包引入

发现业务组件库通过 npm 引入的原子组件库,而项目本身又是通过 mf 引入的原子组件库,相对于引入了 2 遍原子组件库。

这时就需要改造业务组件库,也改成用 mf 的方法引入。

1.8 避免 esm 依赖嵌套

因为 webpack 的按需加载是通过 import、export 来标记的,因此想要一个好的按需加载的效果,就需要避免依赖嵌套的问题。

1.9 图标按需加载

原子组件库 mf 暴露的方式会导致只用了 1 个 icon,就会加载组件库下所有 icon 对应的 chunk,导致资源浪费。

新建一个 icon 的 npm 包用于 icon 的按需引入。

1.10 小结

通过以上优化手段,体积从 11.7mb 降低至 1.1mb,降低 10.6 倍。

优化前:

优化前

优化后:

优化后

2. 图片优化

1.1 图片懒加载

对非首屏的图片采用图片懒加载策略。

1.2 图片尺寸

使用图片时,设置图片的合理尺寸。

1.3 图片格式设置

优先使用 webp 格式图片。

四、优化最佳实践

1. 设置 CSP 策略

2. 设置合理的图片的分辨率

优化项目内的图片分辨率。

五、优化 SEO

1. meta description、keywords 优化

详细的 meta description、keywords 可以加快 SEO。

<meta name="keywords" content="xx" /> <meta name="description" content="xx" />




2. 图片加上 alt 属性

<img src="smiley.gif" alt="Smiley face" />




六、优化前后对比

再来回顾下前后对比:

优化前,明显的感知白屏时间长:

优化前

优化后,在清缓存的情况下也能实现秒开:

优化后

整体性能提升 270%:

优化前后对比

七、性能监控

为了在后续的迭代过程中,保持高性能,引入内部前端监控平台 -烛龙,可视化的监控前端性能。

第一步,加载 cdn 插件:

<script
  defer
  src="https://h5static.m.jd.com/act/jd-jssdk/latest/jd-jssdk.min.js"
></script>




第二步,在入口文件中,初始化 cdn 插件:

useEffect(() => {
  // 初始化测速组件,在这里可以打开一些控制的开关,如是否上报接口
  if (IS_PROD) {
    // @ts-ignore
    jmfe.profilerInit({
      flag: xxx, // 这是应用ID,需要先在烛龙申请应用
      autoReport: true,
      autoAddStaticReport: true,
      autoAddApiReport: true,
      autoAddImageReport: false, // 支持所有图片上报,如果图片多,切记关闭,否则存在性能问题
      performanceReportTime: 8000,
      profilingRate: 1,
    })
  }
}, [])




第三步,查看监控数据:

在烛龙平台,小工具性能评分达 96分:

查看监控数据

第四步,新增告警,实时监控

烛龙平台支持多维度的告警的服务,增加性能指标相关的告警,在性能异动时,及时发现问题,优化性能。

小结

本文详细介绍了一个前端项目优化的详细过程,从优化前的问题分析,到具体的优化措施,最终实现了前端性能提升了近 3 倍。同时也将性能指标落到监控平台,实现可视化的监控前端性能指标。

希望能对你有所帮助,感谢阅读~

参考资料

作者:京东零售 唐姣

来源:京东云开发者社区

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

实践指南-前端性能提升 270% 的相关文章

  • 如何将 Live API for Contacts 的响应中的哈希值转换为文本

    我集成了 Live JS api 来获取用户的实时联系人 它以哈希格式 email hash 返回电子邮件 我如何使用 javascript 或 c net 转换为可读文本 非常感谢 我遇到了同样的问题 并且找到了解决方案 您所需要做的就是
  • 更改样式表 JavaScript

    我得到了这个 HTML 代码
  • 如何使用 lodash、underscore 或 bluebird 同步迭代数组 [关闭]

    Closed 这个问题需要细节或清晰度 help closed questions 目前不接受答案 我有一个数组 其中每个索引处包含文件名 我想下载这些文件一次一个 同步 我知道关于 Async 模块 但我想知道是否有任何功能Lodash
  • 如何查询和过滤 Firebase 实时数据库 [重复]

    这个问题在这里已经有答案了 我想从数据库中获取所有人员 其中名字和姓氏由用户输入给出 到目前为止 这是我的代码 admin database ref persons orderByChild Firstname equalTo firstN
  • 使用ajax发送表单数据

    我想用 ajax 以表单形式发送所有输入 我有一个这样的表单
  • ECMAScript 6 类中的 getter 和 setter 有何用途?

    我对 ECMAScript 6 类中 getter 和 setter 的意义感到困惑 什么目的 下面是我参考的一个例子 class Employee constructor name this name name doWork return
  • 按 Enter 键提交消息?

    我正在开发一个基于本教程使用 Meteor 构建的聊天应用程序 http code tutsplus com tutorials real time messaging for meteor with meteor streams net
  • Durandal SPA 与打字稿有关的问题

    我使用 TypeScript 1 8 将我的 durandal SPA 应用程序从 VS 2012 更新到 VS 2015 它将生成 JavaScript ECMA5 我解决了所有构建错误 但我无法修复一个名为 return 语句只能在函数
  • 如何格式化折线图谷歌图表材料上的轴?

    我在格式化材料图表的轴时遇到问题 Using classic line chart if I would like to format my vertical axis with a dollar sign I would do vAxes
  • linkedin js 如何是有效的 javascript

    LinkedIn Javascript 集成是通过以下方式完成的 我不明白 这怎么是一个有效的javascript 为什么 api key 没有被引用 脚本标签的主体带有src永远不会被执行 但是 加载的脚本可以像访问任何其他元素的内容一样
  • React Native 中 fontAwesome 图标的圆形轮廓

    我想使用 fontAwesome 图标 使其位于圆圈的中间 我想将它用作一个图标项 我读到我们可以将它与圆形图标一起使用并将其放置在其中 但我无法使其工作 import IconFA from react native vector ico
  • FileReader 在 Ionic 2 中未触发 onloadend

    我正在尝试使用 cordova file plugin 读取本地文件 目前我可以读取本地目录的内容并选择单个文件 但我在获取文件内容时遇到问题 这是我的函数 从列表中选择文件后单击按钮即可调用该函数 import window resolv
  • axios 如何将 blob 与 arraybuffer 作为响应类型处理?

    我正在下载一个 zip 文件axios https www npmjs com package axios 为了进一步处理 我需要获取已下载的 原始 数据 据我所知 Javascript 有两种类型 Blob 和 Arraybuffers
  • 使标签充当输入按钮

    我怎样才能做一个 a href http test com tag test Test a 就像表单按钮一样 通过充当表单按钮 我的意思是 当单击链接执行操作时method get 或 post 以便能够通过 get 或 post 捕获它
  • 如何使用 ReactJS 使表中的列可以以两种方式排序

    我正在 ReactJS 中构建一个简单的应用程序 它通过调用某个 API 来使用 JSON 数组 然后我将数组的结果填充到表中 我现在想让表的列可排序 我理想的情况是同时进行升序和降序排序 一旦我单击标题 当它按升序排序时 它应该按降序排序
  • JavaScript 中的安全数据

    我必须为 Web 测试创建生成器 使用 HTML 和 JavaScript 测试必须离线和在线进行 正确答案和分数评估必须是生成的测试的一部分 最终用户的分数仅发送到服务器 无法在服务器上进行评估 并且服务器对问题一无所知 它只保存最终分数
  • 数据表 - 从 AJAX 源过滤数据

    我有一个数据表 正在从 api 获取数据 现在我的状态是活动的 非活动的 如果标志是活动的 那么我需要在数据表中显示 否则我不应该显示过期的 这是我的fiddle https jsfiddle net lakshmipriya001 qLp
  • 使用 NodeJS 创建 YouTube 播放列表

    我正在尝试使用 NodeJS 服务器创建 YouTube 播放列表 我已按照 Oauth 的 NodeJS 快速入门说明进行操作 如以下链接所示 https github com youtube api samples blob maste
  • 从 node.js 创建对 AWS ES 实例的有效签名请求

    我试图找到一个示例 说明如何连接到 Node js 中的 AWS ES 实例 然后通过一个简单的请求访问 ES 集群 我正在尝试使用elasticsearch节点包 https www npmjs com package elasticse
  • javascript 加壳器与压缩器

    我想知道加壳器与压缩器的区别 优点是什么 即您应该在网络应用程序中部署压缩版本还是压缩版本 示例代码 var layout NAVVISIBLE 1 Init function this Resize Dimensions function

随机推荐

  • 闭环系统的零极点图判定稳定性_系统的稳定性判别

    pzmap 函数可以绘制连续系统在复平面内的零极点图 其调用格式如下 p z pamap num den 或 p z pzmap A B C D 或 p z pzmap p z 其中列向量 p 为系统的极点 列向量 z 为系统的零点 num
  • SQLilabs的第20关(HTTP请求头-Cookie)——报错注入

    1 判断闭合方式 我们在cookie的后面加上一个 返回页面如下 我们再将 改成 返回页面如下 这说明闭合方式是 2 确定注入方式 我们在判断闭合方式时发现 该网站会返回报错信息 又没有回显 因此适合使用报错注入 3 爆破数据库名 用户名
  • opencv中morphologyEx()函数

    opencv中morphologyEx函数 函数原型 参数解释 例子 相关函数 参考博客 函数原型 CV EXPORTS W void morphologyEx InputArray src OutputArray dst int op I
  • pnpm 构建 Monorepo workspace项目

    pnpm 构建 Monorepo 项目 使用背景 因为公司要做的项目比较多 项目之间又会相互依赖 目前分为pc后台 pc商城 uniapp项目等等 所以为了代码的复用和代码的规范提交 决定引入pnpm来创建Monorepo项目 Monore
  • 每次win10开机需要重启一次系统才能进去,第一次停留在启动画面就不动了。

    这是由于部分电脑的主板不支持快速启动造成的 所以把快速启动功能关闭掉即可 具体操作步骤如下 控制面板 硬件和声音 电源选项 选择电源按钮的功能 选择 更改当前不可用的设置 然后把 启用快速启动 推荐 前面的勾去掉 再点击下面的 保存设置 即
  • Python 自动化测试(三): pytest 参数化测试用例构建

    在之前的文章中主要分享了 pytest 的实用特性 接下来讲 Pytest 参数化用例的构建 如果待测试的输入与输出是一组数据 可以把测试数据组织起来用不同的测试数据调用相同的测试方法 参数化顾名思义就是把不同的参数 写到一个集合里 然后程
  • Jetson Nano复制系统和U盘启动【第三部分】

    一 写在前面 第三部分承接第二部分 由于Nano EMMC容量只有16GB大小 安装系统和SDK后 Nano EMMC只剩下1 4GB容量 几乎没有空间安装其它软件 第三部分的主要内容是将Nano EMMC系统完全复制到U盘中 并修改Nan
  • 经验模式分解(EMD)——简介及Matlab工具箱安装

    最近在做脑电信号分析 在导师的建议下学习了一点经验模式分解 下面简称EMD 的皮毛 期间也是遇到了很多问题 在这里整理出来 一是为了自己备忘 二是为了能尽量帮到有需要的朋友 一 EMD简介 经验模态分解 Empirical Mode Dec
  • Oracle数据库 SQL Plus 命令使用指南

    熟悉oracle的朋友都知道 SQL PLUS是一个重要的和ORACLE打交道的工具 SQL PLUS本身有很多命令 可以帮助我们做很多事情 包括产生一些规格化的报表 提供人机交互等等 下面 我就简单地说明一下 供大家参考 一 帮助命令 H
  • Java有哪些基本数据类型?

    在Java中 有8种基本数据类型 它们分为两种类型 值类型 Primitive types byte 字节型 占用1个字节 表示范围为 128 127 short 短整型 占用2个字节 表示范围为 32768 32767 int 整型 占用
  • Spring Boot 框架总结

    Spring Boot 框架总结 1 springboot的引言 Spring Boot是由Pivotal团队提供的全新框架 其设计目的是用来简化Spring应用的 初始搭建以及开发过程 该框架使用了特定的方式来进行配置 从而使开发人员不
  • SAP S4 FI后台详细配置教程- PART5 (应收帐目和应付帐目配置篇)

    SAP S4 FI后台详细配置教程 PART5 应收帐目和应付帐目配置篇 1 客户 1 1 定义客户科目组 概念功能说明 客户是按照账户组来管理的 可以通过定义客户科目组来进行区 如一般客户 集团内客户 一 次性客户等 客户主数据信息分三个
  • hive add jar 报java.net.UnknownHostException: user错误

    hive gt add jar hdfs mypath myjar jar java net UnknownHostException user Query returned non zero code 1 cause java net U
  • v3s 荔枝派zero开发板 添加 ov2640 摄像头(一)

    1 准备 储备知识 1 DVP是并口传输 速度较慢 传输的带宽低 使用需要PCLK sensor输出时钟 MCLK XCLK 外部时钟输入 VSYNC 场同步 HSYNC 行同步 D 0 11 并口数据 可以是8 10 12bit数据位数大
  • LA@n维向量@解析几何向量和线性代数向量

    文章目录 概念 n维向量 向量类型 实向量和复向量 行向量和列向量 行列向量的转换 特殊向量 向量运算 矩阵的向量分块 解析几何向量和线性代数向量 向量空间 n n n维向量空间
  • JSONObject详解

    JSONObject只是一种数据结构 可以理解为JSON格式的数据结构 key value 结构 可以使用put方法给json对象添加元素 JSONObject可以很方便的转换成字符串 也可以很方便的把其他对象转换成JSONObject对象
  • 微服务架构的主要优势是什么

    微服务架构提供了几个关键优势 使其成为设计和构建应用程序的流行选择 以下是微服务架构的一些显着优势 可扩展性 微服务架构允许单个服务根据其特定需求独立扩展 这种可扩展性可实现高效的资源利用 并能够通过仅扩展必要的服务来处理高流量负载 它可以
  • Kbuild系统源码分析(五)—模块的编译流程

    版权声明 本文为CSDN博主 ashimida 的原创文章 遵循CC 4 0 BY SA版权协议 转载请附上原文出处链接及本声明 原文链接 https blog csdn net lidan113lidan article details
  • 手机黑屏摄像app_手机黑屏摄像软件下载-手机黑屏摄像持续拍摄app1.3安卓版下载_骑士下载...

    手机黑屏摄像持续拍摄app这是一款支持黑屏状态下拍摄的软件 如果你有这方面的需要 可以来试试的 不会让人发现你在拍摄 软件中有黑屏模式 你打开就可以了 使用起来简单 操作也方便 需要的朋友赶紧下载试试吧 软件介绍 能够根据手机上黑屏状态下还
  • 实践指南-前端性能提升 270%

    一 背景 当我们疲于开发一个接一个的需求时 很容易忘记去关注网站的性能 到了某一个节点 猛地发现 随着越来越多代码的堆积 网站变得越来越慢 本文就是从这样的一个背景出发 着手优化网站的前端性能 并总结出一套开发习惯 让我们在日常开发时 也保