性能优化之思路和分析

news2025/1/18 10:08:30

、优化思路

  1. 尽可能减少首屏必须资源的体积
  2. 尽可能提前首屏必须资源/接口的请求发起时机
  3. 延后+闲时预缓存非必要资源/请求

代码分离
https://webpack.docschina.org/guides/code-splitting/

动态导入
https://webpack.docschina.org/guides/code-splitting/#dynamic-imports

splitChunk
https://webpack.docschina.org/plugins/split-chunks-plugin/

预获取/预加载模块(prefetch/preload module)

bundle 分析(bundle analysis)

缓存

资源使用覆盖率

1. Scm build 并上传到 CDN

主要关注产物体积,常见的有

  1. 依赖重复打包
  2. 有没有 Treeshaking/按需引入
  3. 没有适当分包(例如所有的包都打包在一个 bundle。[contentHash].js 中,
    那么每次更新业务代码或更新依赖包版本都会使得 hash 值改变,每次发布后用户都必须重新下载所有资源
  4. 没有适当分包还会使得首屏访问时,下载很多非首屏必须的资源(检查资源使用覆盖率)
  5. 打包压缩、服务器 gzip

2. 请求 HTML 文档,等待 HTML 文档返回(可能有未登录重定向),此时处于白屏状态

  1. 主要关注 html 的返回耗时

3. HTML 下载完后 ,通过浏览器的预加载器推测出页面所需的资源并按特定顺序发起请求

  1. 资源请求发起顺序是否合理(必须资源尽快发起,非必须资源延后)

4. 从上往下,下载解析执行 HTML 文档的 head 标签,如果有 css/js ,将阻塞之后的资源的执行。

  1. 因为会堵塞后面的流程,所以这里的 css 和 js 最好是尽量精简,只加载首屏必须(检查资源使用覆盖率)
  2. 检查是否命中浏览器强缓存/协商缓存 ,每次更新代码重新部署后有多少资源仍然能命中缓存

5. 对 HTML 文档的 body 标签进行解析渲染,因为 SPA 项目中 index.html body

一般只有一个空的容器标签,所以页面依然是白屏 。
  1. 可以在 html 中直接打入 loading 组件 or 骨架屏的代码并在此阶段展示,白屏比较影响体验

6. 依次下载解析执行 body 标签中的 js 和 css 。界面依然白屏,直到 ReactDOM.render(, document.getElementById(‘root’)) 触发后,界面开始渲染大体外框(侧边栏/头部导航栏),并开始请求 UserInfo、UserAuth、AppInfo 等全局状态。

  1. 关注资源的请求发起时机以及是否是首屏必须资源
  2. 一些接口可以预取, 接口获取权限数据,并且在获取权限数据前会阻塞组件渲染。
    因此我们可以把该接口请求时机提前,能有效提升体验。 推荐的预取方式是 Link preload

7. 进入 react-router,如使用了代码分割动态加载

8. 调用 API 获取到业务数据后,填充进页面,展示出最终的页面内容。

  1. 一般到这就是 LCP 和 TTI 的时间点,我们的优化目标就是把这个时间点提前

三、产物分析

在众多性能优化项中,产物体积优化是最容易拿到性能收益的一项。
移除页面上的非必须资源不仅能减少网络传输时间, 
也能减少 CPU 的解析/编译时间和潜在的内存开销。

社区有挺多开源的分析工具:

  • webpack-chart: webpack stats 可交互饼图。
    https://alexkuz.github.io/webpack-chart/

  • webpack-visualizer: 可视化并分析你的 bundle,检查哪些模块占用空间,哪些可能是重复使用的。
    https://chrisbateman.github.io/webpack-visualizer/

  • webpack-bundle-analyzer:一个 plugin 和 CLI 工具,
    它将 bundle 内容展示为一个便捷的、交互式、可缩放的树状图形式。
    https://github.com/webpack-contrib/webpack-bundle-analyzer

  • webpack bundle optimize helper:这个工具会分析你的 bundle,
    并提供可操作的改进措施,以减少 bundle 的大小。
    https://webpack.jakoblind.no/optimize/

    • bundle-stats:生成一个 bundle 报告(bundle 大小、资源、模块),
      并比较不同构建之间的结果。
      https://webpack.docschina.org/api/stats/

优化案例

https://www.cnblogs.com/cczlovexw/p/14187645.html
https://loadable-components.com/docs/code-splitting/
重复打包
按需加载
webpack拆分最正确的办法
https://david-gilbertson.medium.com/the-100-correct-way-to-split-your-chunks-with-webpack-f8a9df5b7758

运行时分析

  1. chrome devtools performance
    https://developer.chrome.com/docs/devtools/performance/
    https://developer.chrome.com/docs/devtools/performance-insights/

  2. 覆盖率
    https://developer.chrome.com/docs/devtools/coverage/

  3. lighthouse会同时记录上面的performance和覆盖率报告
    https://developer.chrome.com/docs/devtools/lighthouse/

  4. 起一个好的chunk name
    https://www.codemzy.com/blog/how-to-name-webpack-chunk

运行时分析最好能做到控制变量。 chrome 提供了限制网速的选项,
但是对于 cpu 性能只提供了按倍速限制的能力(用于模拟移动端性能)

  1. 先从 pv 最高、tti 也比较高的页面开始
  2. 用 chrome 无痕模式
  3. 网络情况:
  4. 停用缓存 (可选)测试页面在无浏览器缓存情况下的加载性能时可以打开
  5. 限速(要小于你的最小网速,不然就没意义了)

、requestAnimationFram

requestAnimationFrame 是浏览器专门为动画提供的 API,
它的刷新频率与显示器的频率保持一致,
使用该 api 可以解决用 setTimeout/setInterval 制作动画卡顿的情况

Web Worker 优化长任务

由于浏览器 GUI 渲染线程与 JS 引擎线程是互斥的关系,
当页面中有很多长任务时,
会造成页面 UI 阻塞,出现界面卡顿、掉帧等情况


	要考虑 web worker的通信时长
 Time 是这个资源的通信时长(也叫加载时长)

proformance火焰图

在这里插入图片描述
在这里插入图片描述


每个资源请求的图形中都存在一左侧线段、浅色矩形、深色矩形、右侧线段:
左侧线段:Request Sent 之前所有时间花费(Queueing ~ Proxy negotiation)。
浅色矩形:Request Sent + Waiting (TTFB)。
深色矩形:Content Download。
右侧线段:等待主线程的时间花费。

一些关注点:

资源的优先级和耗时。鼠标悬浮到对应资源上可以看到资源优先级(Highest、High、medium、Low、Lowest)。

检查是否有 Highest 的非关键资源,或者是否存在某些关键资源以 Low、Lowest 优先级进行加载;

资源加载各阶段耗时。资源矩形的长度体现了耗时,鼠标悬浮到对应资源上可以看到具体耗时和时间组成。
检查是否存在耗时较长的资源、队列或主线程等待时间是否符合预期、是否影响到其他关键资源。

加载顺序。某些关键资源的请求路径较深,是否可以提前加载,详见预加载关键资源。

资源开始加载、完成、执行的时机(FP、FCP、LCP...)是否符合预期。

关键资源耗时,在 Network 的瀑布图可以做更具体的耗时分析

Queueing:队列等待时间。以下情况下请求会进行排队:

存在更高优先级的请求;


同源仅能打开六个 TCP 连接的限制(仅适用于 HTTP/1.0 和 HTTP/1.1);

浏览器需要在磁盘缓存中短暂分配空间。

Stalled:请求停滞。请求可能因排队中所述的任何原因而停止。

DNS Lookup:DNS 查找。浏览器正在解析请求的 IP 地址。

Initial connection:初始连接。浏览器正在建立连接,包括 TCP 握手/重试和协商 SSL.

Proxy negotiation:代理协商。浏览器正在与 proxy server 协商请求。

Request sent:请求已发送。正在发送请求。

ServiceWorker Preparation: ServiceWorker 准备。浏览器正在启动 Service Worker。

Request to ServiceWorker: 请求 ServiceWorker。请求正在发送给 service worker.

Waiting (TTFB): 等待(TTFB,Time To First Byte)。
浏览器正在等待响应返回的第一个字节,此时间包括 1 次往返延迟和服务器准备响应所用的时间。

Content Download:内容下载。浏览器直接从网络或 Service Worker 接收响应。

Content Download 表示读取响应内容所花费的总时间。大于预期的值可能表示网络速度较慢,
或者浏览器正忙于执行其他工作,从而延迟了响应的读取。

Receiving Push:接收推送。浏览器正在通过 HTTP/2 服务器推送接收此响应的数据。

Reading Push: 读取推送。浏览器正在读取之前接收到的本地数据。

参考链接
掘金地址点击查看

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/556733.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

vector模拟

先来看看vector的源码&#xff0c;string没有看是因为string严格意义上来讲不属于STL。 源代码之间也是存在区别的&#xff0c;大同小异&#xff0c;可以去网上查如何下载STL的源码库。 先看看<vector>文件中的内容&#xff08;当做参考即可&#xff09;&#xff1a; 内容…

springboot服务端接口公网远程调试 - 实现HTTP服务监听【端口映射】

文章目录 前言1. 本地环境搭建1.1 环境参数1.2 搭建springboot服务项目 2. 内网穿透2.1 安装配置cpolar内网穿透2.1.1 windows系统2.1.2 linux系统 2.2 创建隧道映射本地端口2.3 测试公网地址 3. 固定公网地址3.1 保留一个二级子域名3.2 配置二级子域名3.2 测试使用固定公网地址…

【分布式系统】分布式锁实现之Redis

锁有资源竞争问题就有一定有锁的存在&#xff0c;存储系统MySQL中&#xff0c;有锁机制保证数据并发访问。而编程语言层面Java中有JUC并发工具包来实现&#xff0c;那么锁解决的问题是什么&#xff1f;主要是在多线程环境下&#xff0c;对共享资源的互斥。从而保证数据一致性。…

SVG在前端中的常见应用

SVG在前端中的常见应用 一、svg标签1. svg2. g 二、描边属性三、模糊和阴影效果1. 模糊2. 阴影效果 四、线性渐变和径向渐变1. 线性渐变2. 径向渐变 五、绘制1. 内置形状元素2. 绘制矩形3. 绘制圆形4. 绘制椭圆5. 绘制线条6. 绘制多边形7. 绘制多线条8. 绘制文本9. 绘制路径 只…

【C/C++】动态内存管理/泛型编程

&#x1f307;个人主页&#xff1a;平凡的小苏 &#x1f4da;学习格言&#xff1a;命运给你一个低的起点&#xff0c;是想看你精彩的翻盘&#xff0c;而不是让你自甘堕落&#xff0c;脚下的路虽然难走&#xff0c;但我还能走&#xff0c;比起向阳而生&#xff0c;我更想尝试逆风…

SQLlite教程(第一篇)

SQLlite教程(第一篇 SQLlite是什么?SQLlite工作原理是什么?SQLlite有什么功能和特性?使用SQLlite有哪些注意事项?附加资料 SQLlite是什么? SQLite&#xff0c;是一款轻型的数据库&#xff0c;是遵守ACID的关系型数据库管理系统&#xff0c;它包含在一个相对小的C库中。它是…

Mysql审核查询平台Archery部署

目录 1 Archery产品介绍2 基于docker搭建Archery2.1 系统环境2.2 安装 Docker2.2.1 安装 Docker Compose2.2.2 下载Archery2.2.3 安装并启动2.2.4 表结构初始化2.2.5 数据初始化2.2.6 创建管理用户2.2.7 退出重启2.2.8 日志查看和问题排查2.2.9 启动成功查看2.2.10 端口占用情况…

基于Maven的profiles多环境配置

一个项目通常都会有多个不同的运行环境&#xff0c;例如开发环境&#xff0c;测试环境、生产环境等。而不同环境的构建过程很可能是不同的&#xff0c;例如数据源配置、插件、以及依赖的版本等。每次将项目部署到不同的环境时&#xff0c;都需要修改相应的配置&#xff0c;这样…

day07_数组初识

数组的概述 数组就是用于存储数据的长度固定的容器&#xff0c;保证多个数据的数据类型要一致。 数组适合做一批同种类型数据的存储 数组中的元素可以是基本数据类型&#xff0c;也可以是引用数据类型。当元素是引用数据类型是&#xff0c;我们称为对象数组。 容器&#xff…

从0开始学C语言的个人心得笔记(10w字)

大学的计算机相关专业第一门教学的计算机语言就是c语言&#xff0c;很多大学生面对从未接触过的计算机语言&#xff0c;可能会觉得很难以上门&#xff0c;从而放弃学习c语言。这篇博客写的主要是个人学习C语言时候的知识总结点&#xff0c;不能保证全部是正确的&#xff0c;如有…

Kafka灵魂28问

第 1 题 Kafka 数据可靠性如何保证&#xff1f; 对于 kafka 来说&#xff0c;以下几个方面来保障消息分发的可靠性&#xff1a; 消息发送的可靠性保障(producer) 消息消费的可靠性保障(consumer) Kafka 集群的可靠性保障&#xff08;Broker&#xff09; 生产者 目前生产者…

Leetcode每日一题——“用队列实现栈”

各位CSDN的uu们你们好呀&#xff0c;好久没有更新本专栏啦&#xff0c;甚是想念&#xff01;&#xff01;&#xff01;今天&#xff0c;小雅兰的学习内容是用队列实现栈&#xff0c;下面&#xff0c;让我们进入Leetcode的世界吧&#xff01;&#xff01;&#xff01; 这是小雅兰…

本地 docker 发布 java 项目,连接本地 redis 配置

1、本地项目 install 相应的 jar 包到 target 目录下&#xff0c;jar 包的路径步骤 2 要填写 2、项目根目录下创建 Dockerfile 文件 # 使用官方的 Java 11 镜像作为基础镜像 FROM openjdk:11-jdk# 设置工作目录 WORKDIR /app# 复制应用程序 JAR 文件到镜像中的 /app 目录下 C…

用LangChain实现一个ChatBlog

文章目录 前言环境一、构建知识库二、将知识库向量化三、召回四、利用LLM做阅读理解五、效果总结 前言 通过本文, 你将学会如何使用langchain来构建一个自己的知识库问答 其实大多数类chatpdf产品的原理都差不多, 我将其简单粗暴地分为以下四步: 构建知识库将知识库向量化召回…

vue diff算法与虚拟dom知识整理(11) 书写patch父级新旧为同一节点 子节点与文字交换逻辑实现

上文我们简单描述了patch处理同一节点的大体逻辑 这次 我们就来看一下text替换的情况 我们更改案例入口文件 src下的 index.js 代码如下 import h from "./snabbdom/h"; import patch from "./snabbdom/patch";const container document.getElementById(…

Maven概念及搭建

1.为什么我们要学习 maven? maven 还未出世的时候&#xff0c;我们有很多痛苦的经历 。 痛点 1&#xff1a; jar 包难以寻找 痛点 2&#xff1a; jar 包依赖的问题 痛点 3&#xff1a; jar 不方便管理 痛点 4&#xff1a;项目编译 2.Maven 简介 Maven 是 Apache 软件基金…

Golang中的管道(channel) 、goroutine与channel实现并发、单向管道、select多路复用以及goroutine panic处理

目录 管道&#xff08;channel&#xff09; 无缓冲管道 有缓冲管道 需要注意 goroutine与channel实现并发 单向管道 定义单向管道 将双向管道转换为单向管道 单向管道作为函数参数 单向管道的代码示例 select多路复用 案例演示 goroutine panic处理 案例演示 管道…

APP服务端架构的演变

大家好&#xff0c;我是易安&#xff01; 早期2013年的时候&#xff0c;随着智能设备的普及和移动互联网的发展&#xff0c;移动端逐渐成为用户的新入口&#xff0c;各个电商平台都开始聚焦移动端App&#xff0c;如今经历了10年的发展&#xff0c;很多电商APP早已经没入历史的洪…

日语文法PPT截图31-45

31 形式名词 とき ところ 作为形式名词的话&#xff0c;一般是要写假名不写汉字的 相对时态 如果是一般时/将来时とき&#xff0c;就是先做后面的动作&#xff0c;在做前面的动作。 出教室的时候&#xff0c;关灯。 如果是过去时とき那么&#xff0c;是先做前面的动作&#…

Linux安装elk

稍后补充。 目录 01【安装elk】 es单机 es集群 esHead插件 kibana logstash elastic search:https://www.elastic.co/cn/downloads/elasticsearchlogstash:https://www.elastic.co/cn/downloads/logstashkibana:https://www.elastic.co/cn/downloads/kibana linux下安装E…