阿里妹导读
作者最近在考试测验对卖力的平台进行性能优化,本文整理了些前端性能优化的一些常见策略。
踏上取经路,比抵达灵山更主要。

一、概览
最近在考试测验对卖力的平台进行性能优化,整理了一下前端性能优化的一些常见策略。一样平常性能优化的常见思路是:前辈行性能现状剖析定义出问题,然后针对问题结合性能优化策略给出技能方案并进行评估,末了再落地&验证技能方案。工欲善其事,必先利其器,让我们跟随本文理解一下常见的性能优化策略。话不多说,先上大纲。
清晰大图见链接或点击文末阅读原文查看:
https://developer.aliyun.com/article/1610662
二、常识趣能优化策略
2.0 前置储备知识点
2.0.1 用户访问页面CRP(用户输入一个URL后会发生什么)前端口试有一个很经典的问题:用户输入一个URL后会发生什么。这个问题可以很有效的稽核候选人知识的广度,乃至于深度。一样平常来说,web真个性能优化,实质上便是尽可能缩短“用户输入一个URL”到“用户可以在网页上进行预期行为”这两个韶光点的韶光间隔。
因此,web性能优化一样平常会被纳入用户体验优化的一环。在一些C端场景,用户可以进行预期行为的耗时,和终极干系页面产生的收益有着很明显的正向关联,网络上可以找到一些干系案例。
以是,在进行性能优化前,我们须要理解我们要优化的东西是什么。也就引出了用户访问页面CRP(关键渲染路径)。大略点说,用户输入URL后一样平常经历如下环节。
浏览器对输入URL的域名进行DNS解析得到IP地址;基于IP地址和目标做事器建连接(http1.1 / http2 / http3);基于建立的连接,向做事器发送http要求;目标做事器处理要求并返回http相应;浏览器收到做事器的相应(我们只考虑先要求html的情形)返回html;浏览器对html进行解析,基于html和js脚本构建dom树,基于css构建cssom树,合成渲染树;结合渲染树和屏幕分辨率等干系信息打算节点布局信息;浏览器基于渲染树和布局信息进行页面绘制;末了将不同的图层合并为终极的图像,涌如今页面上;核心公式:“用户访问页面耗时” = “资源要求耗时” + “页面渲染耗时”。参考下方示意图:
2.0.2 浏览器的进程和线程机制
优化策略中有涉及web worker 等观点,web worker是基于后台线程去运行的,以是不才图大略先容下浏览器的进程和线程机制。
2.0.3 页面重绘&重排(回流)
重绘是指当元素的外不雅观(如颜色、背景、阴影等)发生变革时,浏览器须要重新绘制这些元素,但不须要重新打算它们的布局。重绘不会影响文档的构造,只是更新了元素的视觉表现。比如改变元素的背景颜色、修正文本的颜色或字体样式。
重排,又称回流,是指当元素的几何属性(如宽度、高度、位置等)发生变革时,浏览器须要重新打算元素的布局。这常日会导致全体文档的布局被重新打算,因此重排的开销比重绘要大得多。比如改变元素的大小(如宽度或高度)、添加或删除 DOM 元素、改变元素的边距、添补或边框。
重绘相对较轻量,常日不会显著影响性能。重排则可能导致性能问题,尤其是在频繁触发时,由于它会影响到全体文档的布局,可能导致多次重排和重绘。
2.1 资源要求环节
2.1.0 优化思路首先我们定义出“资源要求耗时”的几个干系成分:要求并发数量、单次要求韶光以及资源要求顺序。个中资源要求顺序并不能直接缩短“资源要求耗时”,但可以让“关键的资源”先完成要求,从而页面渲染先行启动。
2.1.1 增加要求并发数量默认情形下,浏览器对同一域名下的并发要求数量有限定,常日为6-8 个。 这意味着浏览器在同一韶光最多同时发送6-8 个要求给同一域名下的做事器。 超过这个数量的要求将会被排队等待。我们可以通过如下方案增加要求并发数量。
2.1.1.1 利用多个域名(又称域名分片、域名负载均衡)域名分片(Domain Sharding)是一种优化技能,旨在提高网页加载速率和资源要求的并发性。其基本事理是将网站的静态资源(如图片、CSS、JavaScript文件等)分散到多个不同的域名或子域名上,以绕过浏览器对同一域名的并发要求限定。
利用多个子域名例如,如果你的主域名是example.com,可以利用static1.example.com、static2.example.com等子域名来托管静态资源。利用不同的顶级域名可以将资源分散到不同的顶级域名上,例如example1.com、example2.com等。CDN支持许多内容分发网络(CDN)许可你利用多个域名来分发内容。2.1.1.2 升级http2HTTP/2 是 HTTP 协议的第二个紧张版本,旨在提高网络性能和效率。在 HTTP/1.x 中,每个要求常日须要建立一个新的 TCP 连接(HTTP/1.0),或者在同一连接上按顺序处理要求(HTTP/1.1,Keep-Alive),这导致了连接建立和关闭的开销。HTTP/2 许可多个要乞降相应在同一连接上并发进行(多路复用特性),减少了连接的数量和延迟。下方先容下HTTP2的多路复用以及其他特性。
多路复用HTTP/2 许可在单个连接上并发发送多个要乞降相应,而不须要等待前一个要求完成。这减少了延迟并提高了资源利用率。头部压缩HTTP/2 利用 HPACK 算法对要乞降相应头部进行压缩,减少了传输的数据量,特殊是在要求头部较大的情形下。做事端推送做事器可以主动向客户端推送资源,而不须要客户端要求。这意味着做事器可以在客户端要求某个页面时,提前发送该页面所需的资源(如 CSS 和 JavaScript 文件)。二进制分帧HTTP/2 利用二进制格式而不是文本格式,这使得解析更高效,减少了缺点的可能性。优先级和流掌握HTTP/2许可客户端为要求设置优先级,做事器可以根据这些优先级来优化资源的发送顺序。此外,流掌握机制可以防止某个流占用过多的带宽2.1.1.3 升级http3HTTP/3是超文本传输协议的第三个紧张版本,它是基于QUIC(快速UDP互联网连接)协议构建的。QUIC最初是由Google设计的,旨在减少延迟并提高Web性能。HTTP/3办理了HTTP/2中存在的一些问题。
减少连接建立韶光HTTP/2 基于 TCP 和 TLS,须要多个来回韶光(RTT)来完成握手。HTTP/3 利用 QUIC 协议,它将加密和传输合并为一个过程,许可在一个 RTT 完成连接建立,在最佳情形下乃至可以在零 RTT 中规复会话。多路复用无壅塞HTTP/2 虽然支持多路复用,但 TCP 层的队头壅塞问题仍旧存在。HTTP/3 通过 QUIC 改进的多路复用能力,在 QUIC 中由于是基于数据报的 UDP,独立的流可以在其他流发生丢包时连续传输,办理了 TCP 的队头壅塞问题。快速丢包规复和拥塞掌握QUIC 实现了更快速的丢包规复机制。TCP 须要等待一段韶光来确认丢包,而 QUIC 可以利用更风雅的确认机制来迅速相应丢包情形,并相应调度拥塞掌握策略。连接迁移QUIC 支持连接迁移,许可客户端在网络环境变革(如从 Wi-Fi 切换到移动网络)时,保持现有的连接状态。在 HTTP/2 这种情形常日会导致连接中断和须要重新建连。2.1.2 缩短单次要求韶光我们比较粗暴的定义一下“单次要求韶光”的打算公式,“单次要求韶光” = “目标资源体积” / “用户网速”。个中我们作为平台方很难去提升“用户网速”,以是就尽可能降落“目标资源体积”。对付前端来说,“目标资源体积”约即是“前端构建产物体积”。这里常规思路有三个:一是从减少构建产物体积;二是网络传输过程中进行压缩;三是启用缓存,直接不要求。
2.1.2.1 减少构建产物体积这一步我们一样平常结合详细前端工程去做。我所参与开拓的前端工程项目利用的是koi4(基于umi4) + webpack,所以是基于koi4和umi体系去先容的。和其他体系比较,事理都一样,详细工程实现的方案上可能会有差异。
常用公共依赖umd + externals化我们常用的根本依赖比如 react/react-dom/antd/lodash/moment 等等,一样平常不会发生变革。我们就通过umd办法合营externals对其进行加载利用,让其长久的缓存在本地即可,每次运用发布也不会导致这些固定缓存失落效。这种方案,对付富文本/图表类大依赖项目来说,还可以有效的提升开拓体验。这个改造第一个须要把稳的是,在微前端架构下,不同子运用所利用的根本依赖版本可能不是那么统一,这个改造针对工程依赖体系统一的项目收益最大。有些依赖升不动的运用可以先放掉,提升roi。第二个须要把稳的是,三方依赖代码中有很多如 antd/es/Button 类的写法,如果此时只针对 antd 配置一个externals会创造antd还是会被打包到产物中。可以通过webpack插件等办法将所有组件的es引用办法也externals掉,确保产物中没有额外的antd。这个feature我们团队在koi4中进行了内置。lodash等同理。代码共享还有module federation方案,不再赘述。适当的代码分割策略(dynamicImport)umi3有一个api是dynamicImport,在umi4中默认开启了这个feature,会按页拆包、按需加载。如果不开启这个feature,我们所有页面都会被打到同一个bundle(umi.js)中,导致首屏加载慢的恐怖。我接手过的一个最夸年夜的项目umijs体积压缩后6MB+,经由大略改了一些配置:(umd + externals + dynamicImport + runtimeImport + treeshaking),压缩后体积降落到了834KB。微前端架构下,umi.js的体积不仅仅影响的是网络加载,还影响微前端架构下qiankun对umi.js的解析速率,从而影响各种性能指标。我们近期对umi.js入口文件体积进行了优化,用户访问链路上整体350KB的体积减少,让FCP从 1000ms -> 750ms,其他指标 LDP/LCP/MCP由于也要前置经历FCP,也有类似效果的提升。开启Tree shakingTree shaking 是一种优化技能,紧张用于 JavaScript 运用程序的构建过程中,尤其是在利用模块化系统(如 ES6 模块)时。它的紧张浸染是肃清未利用的代码,从而减小最终生成的文件大小,提高加载速率和性能。Tree shaking 通过package.json中增加 "sideEffects": false开启,也可以配置绕过特定文件。开启Tree shaking 紧张关注的是项目代码中有无“副浸染”存在,如果有的话“副浸染”代码被误干掉后会造成干系问题。但是常规项目一样平常也不会有这么多副浸染。我之前碰着的一段副浸染代码是接手的代码中通过 import 'xxx' 引用实行了一段js脚本,导致开启 Tree shaking 后干系代码被干掉,从而页面白屏。// edges/index.tsximport { Graph, Path } from '@antv/x6';import { GraphEdge, GRID_SIZE } from '../../constants';Graph.registerEdge(xxxx);Graph.registerConnector(xxx);// index.tsximport './components/edges';
打包压缩umi中cssMinifier,可以选择利用 esbuild / cssnano / parcelCSS 中的一个对css进行压缩,默认esbuild。jsMinifier,可以利用 esbuild / terser / swc / uglifyJs 中的一个对js进行压缩,默认esbuild。html压缩,不同的打包体系也有不同的插件可以对html进行压缩,这个收益就比较低。webpack可以通过配置 TerserPlugin 来压缩JavaScript代码。rollup可以利用 rollup-plugin-terser 来压缩js代码。其他工程体系一样平常都会有对应的内置压缩插件。umi4关闭不须要的插件umi4会默认开启不少不须要的插件,可以按需关闭。antd: false,如果将antd改造为umd+externals加载,一样平常我们就不须要这个,按需实现就好。locale: false,按需配置就好。helmet: false,如果你都没听过这个,那就直接关了吧。
一样平常用的都是gzip压缩。gzip压缩是一种广泛利用的数据压缩技能,紧张用于减少文件大小以提高传输效率。做事端或者nginx配置一下开启就好。我们如果利用DEF打包项目扔到CDN上的话,g.alicdn.com也默认支持gzip压缩。
工程中的压缩紧张是通过删除无用代码等减小文件体积,gzip压缩是在文件在网络传输过程中进行压缩。
2.1.2.3 缓存静态资源和关键接口
首先我们明确一下缓存工具:前端静态资源(如js/css/image等)以及对实时性哀求不高但是在CRP中block后续渲染的接口(比如用户固定信息/菜单数据)等等。我们目前常涉及的缓存方案包括:CDN边缘节点缓存、HTTP缓存、service-worker缓存以及web存储API(localstorage/sessionstorage/indexdb)。我们一样平常不用Web存储API缓存静态资源,由于其空间有限。
CDN边缘节点缓存CDN(内容分发网络)边缘节点缓存是指在CDN网络中的各个边缘节点(也称为缓存做事器)上存储的内容,以提高用户访问速率和降落源做事器包袱。大略点说,便是拉近和终端用户的物理位置,缓存在离用户最近的CDN节点。http缓存http缓存分为 强缓存 和 协商缓存,http缓存流程如下。如何判断强缓存是否过期?ExpiresExpires 是HTTP/1.0引入的头部字段,用于指定一个特定的日期和韶光,在这个韶光点,相应被视为过期。它的值是一个HTTP日期格式的字符串(绝对韶光)。Cache-ControlCache-Control 是HTTP/1.1引入的头部字段,可以更精确地掌握缓存策略。它可以包含多个指令,每个指令之间用逗号分隔。public : 表示相应可以被任何缓存所存储。private : 表示相应只能被单个用户的缓存存储,比如上方的CDN就无法缓存了。no-cache : 逼迫缓存必须先去协商后端(即,再要求一次)再利用缓存。no-store : 不许可缓存存储任何关于客户端要求或做事器相应的信息。max-age=<seconds> : 指定相应的最大缓存韶光,单位为秒。超过这个韶光,缓存会被视为过期。must-revalidate : 表示缓存必须在利用过期数据之提高行重新验证。service worker缓存service worker 是 PWA 的核心技能,用作网络浏览器和网络做事器之间的代理。它们旨在通过供应离线访问功能来提高可靠性,同时提升网页性能。service worker 紧张是针对弱网或者离线场景,在我们的 web性能优化 场景中,特殊是中后台场景,相对付 http缓存 貌似并没有太大上风。我们经由调研,准备用 service worker 采取 Stale While Revalidate缓存策略 缓存首次访问的html以及对实时性哀求不高但是在CRP中block后续流程的接口。缘故原由如下。我们一样平常会向首屏html注入很多额外接口查询的数据,比如用户信息,导致对首屏html的访问有 150-300ms。经历了这150-300ms,后续要乞降渲染流程才会启动。这个缓存策略可以提升全站访问速率 150-300ms(取决于html要求耗时)。对实时性哀求不高但是在CRP中block后续流程的接口,同理。至于这些接口为什么意外验测验用localstorage等缓存?举个例子,我们的导航和加载器是umd方案引入的,如果每个都改造本钱还是挺高的。通过 service worker 可以实现全局拦截。类似 filter 和 interceptor。为什么采取 Stale While Revalidate 缓存策略?如果硬控html等10分钟,万一我们的某次发版存在bug,那就抓瞎了。web存储APIweb存储API 供应了几种机制来在客户端存储数据,使得web运用能够像桌面运用一样持久化数据。我们一样平常用 web存储API 对一些对实时性哀求较低的数据接口(比如字典)进行缓存,提升页面性能。localStorage利用 localStorage 存储的数据是持久性的,这意味着除非用户或脚本显式地删除它,否则数据会一贯存在。存储空间常日是 5MB 或更多。sessionStorage与 localStorage 不同,sessionStorage 中的数据只存在于浏览器的一个会话期间。当浏览器窗口关闭时,存储的数据会被打消。sessionStorage 的存储容量每每与 localStorage 相同,但在某些实现中可能会更少。indexedDBindexedDB 是一种客户端侧的 NoSQL 数据库技能,许可 Web 运用程序在用户浏览器中存储大量的构造化数据。与 localStorage 和 sessionStorage 比较,IndexedDB 供应了更加强大的数据存储功能,支持事务处理、索引以及繁芜的查询能力。一样平常 indexedDB 的存储空间在 250MB 及以上,如果用户赞许的话,还可以进一步拓展。2.1.3 优化资源要求顺序2.1.3.1 关键资源尽早加载dns-prefetch,DNS预获取DNS预获取许可浏览器在页面加载早期就开始进行DNS查询。这对付跨域资源尤其有用,由于它可以减少由于DNS解析带来的延迟。用法如下。<link rel="dns-prefetch" href="https://example.com">
preconnect,域名预连接预连接许可浏览器尽早建立与第三方资源做事器的连接。这包括DNS查询、TCP握手以及TLS协商。通过预连接,浏览器可以在实际要求资源之前就准备好网络连接,从而加速资源的***。用法如下。
<link rel="preconnect" href="https://fonts.gstatic.com">
如果资源须要HTTPS连接,可以添加 crossorigin 属性。
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
preload,提升资源加载的优先级预加载许可开拓者奉告浏览器立即加载某些资源,纵然这些资源不是立即须要的。这常日用于那些对用户体验至关主要的资源,比如关键css或js文件。通过预加载,浏览器可以在用户实际须要这些资源之前就提前加载它们,从而减少延迟。个中,as 属性指定了要预加载的资源类型。用法如下。
<link rel="preload" href="/style.css" as="style"><link rel="preload" href="/script.js" as="script">
prefetch,预加载其他页面用到的资源预获取许可浏览器在空闲韶光预先***将来可能须要的资源。这常日用于那些用户可能会访问的下一个页面的资源,例如链接到的其他页面。预获取是在用户尚未要求资源之前就开始***资源的技能,它有助于减少未来要求的延迟。用法如下。
<link rel="prefetch" href="/next-page.html"><link rel="prefetch" href="/image.jpg" as="image">
须要把稳的是,过度利用 preload 和 prefetch 可能会导致不必要的带宽花费,因此该当谨慎选择哪些资源进行 preload 或 prefetch。preconnect 和 dns-prefetch 同理,按需合理利用最好。2.1.3.2 非关键资源延迟加载&实行async对付普通脚本,如果存在 async 属性,那么普通脚本会被并行要求,并尽快解析和实行。对付模块脚本,如果存在 async 属性,那么脚本及其所有依赖都会被并行要求,并尽快解析和实行。deferdefer属性的浸染是见告浏览器在HTML文档解析完成后且页面加载之前实行脚本。这样可以确保脚本不会壅塞页面渲染,并且所有元素都在DOM中可用。defer 会壅塞DOMContentLoaded事宜触发。关于async 和 defer的几个把稳事变async 和 defer 这两个属性会让相应js实行不壅塞主线程,但是其加载还是按正常顺序加载的。实行只是延后,但是还是会在主线程上实行。async设置后,其实行顺序是不愿定的;如果对实行顺序有哀求,可以利用defer。按需加载对付公共依赖,我们团队同学开拓了一个umi插件——umi-plugin-runtime-import[1](umi-plugin-runtime-import-v4[2],针对umi4)。比如我们进行上方 umd + externals 加载方案改造的话,大量的umd前置加载会让首屏加载不堪重负。如果利用async方案的话,可能会涌现页面代码实行了,umd还没实行完,从而引发白屏。runtimeImport插件可以对这些umd实现按需引入,只有当页面中利用了这个umd对应的依赖,才会去加载。从而办理 umd + externals 改造带来的首屏加载问题。针对页面级别代码,umi自带dynamicImport实现按页拆包,按需加载机制。这两个方案虽然是umi的插件机制,但是底层都是利用了 webpack 干系能力,其他工程体系也可以参考实现自己的方案。
2.2 页面渲染环节
2.2.0 优化思路资源要求环节的优化是为了让页面渲染的资源尽可能快的ready,然后进行页面的渲染。在页面渲染环节,我们回顾一下页面渲染CRP。
浏览器对html进行解析,基于html和js脚本构建dom树,基于css构建cssom树,合成渲染树;结合渲染树和屏幕分辨率等干系信息打算节点布局信息;浏览器基于渲染树和布局信息进行页面绘制;末了将不同的图层合并为终极的图像,涌如今页面上;首先,肯定离不开SSR这个旧调重弹的优化方案。其次,我们当前重点关注CRP中几个常规web场景下的性能影响成分:JS代码、CSS代码、HTML代码、图片加载以及动画。可能不同业务场景下关注的重点不一样,其他的比如 WebGL、***编码解码以及文档编辑器等等不再展开。
2.2.1 做事端渲染SSRSSR(Server-Side Rendering,做事器端渲染)是一种网页渲染技能,它在做事器上天生完全的 HTML 页面,然后将其发送到客户端(浏览器)。与客户端渲染(CSR)比较,SSR 在用户要求页面时,做事器会处理所有的渲染逻辑,并将天生的页面直接返回给用户。优点:更快的首屏加载韶光;SEO 友好;更好的性能,降落一部分客户端包袱。缺陷:须要做事器资源,且流量高场景下做事器包袱较重,可能非C端场景团队内推动SSR不是那么随意马虎;开拓较繁芜,特殊是处理数据获取和状态管理时;交互存在延迟,也便是SSR页面初次加载时须要额外的js才能实现动态交互。总结:真正利用还是要考虑场景和roi,相对SSR带来的收益,启用SSR带来的本钱是否可以接管。2.2.2 JS代码性能优化2.2.2.1 DOM优化减少 DOM 操作DOM 操作常日是性能瓶颈,由于每次对 DOM 的修正都会导致浏览看重新打算样式、布局和重绘。减少 DOM 操作可以显著提高性能。批量进行 DOM 变动批量更新 是指将多个 DOM 操作合并为一次操作,以减少重排和重绘的次数。常日可以用 DocumentFragment 和 innerHTML 方案实现。简化 HTML 代码简化 HTML 代码是指减少不必要的 DOM 节点和繁芜的构造,以提高性能。包括减少嵌套、移除不必要的元素。利用 虚拟DOM当代前端框架中,实在我们已经很少直接操作 DOM,而是利用 React 和 Vue 这类采取了虚拟DOM技能的前端框架。虚拟DOM 通过在内存中掩护一个虚拟的 DOM 树,减少直接对真实 DOM 的操作,从而提高了性能和相应速率。由于 虚拟DOM 本身特性(新旧树Diff)缘故原由,在如了局景会导致一些性能问题:频繁的状态更新、组件树过于弘大等。不过这些问题目前也有成熟的办理方案。事宜委托事宜委托是一种高效的事宜处理技能,紧张用于减少事宜处理程序的数量,提高性能和简化代码。它的基本事理是将事宜处理程序添加到父元素上,而不是每个子元素上。比如一个卡片包含100个循环渲染出来的数字,我们要对数字点击进行监听。一种办法是给每个数字上加监听,这样就要加100个监听器。其余一种办法便是直接给卡片添加一个监听器,结合事宜冒泡机制,通过event.target判断是对哪个数字的点击,从而实行相应的操作。及时删除不再须要的事宜监听器不再赘述,不用了就及时清理,减少内存占用,避免意外行为。2.2.2.2 函数任务优化Web WorkerWeb Worker 是一种在浏览器中运行 JavaScript 的机制,许可开拓者在后台线程中实行脚本,从而实现多线程处理。它的紧张目的是提高网页的性能,尤其是在处理大量打算或 I/O 操作时,避免壅塞主线程(UI 线程)。详情参考 MDN Web Workers API[3]。WebGPUWebGPU 是一种新的 Web API,旨在为网页供应高性能的图形和打算能力。它许可开拓者利用 GPU(图形处理单元)进行并行打算,从而加速图形渲染和数据处理。详情参考 MDN WebGPU API[4]。长任务处理在 JavaScript 中,长任务指的是那些须要较永劫光才能完成的操作,例如繁芜的打算、大量的数据处理或网络要求等。这些长任务如果在主线程中实行,会导致用户界面冻结,影响用户体验。针对长任务,常见处理策略如下将长任务分解为多个小任务,并利用 setTimeout 或 setInterval 将它们分批实行。这样可以让浏览器有机会处理其他事宜(如用户输入、渲染等)。将长任务移到 Web Worker 中实行。Web Worker 在后台线程中运行,不会壅塞主线程,适宜处理繁芜打算或大量数据。对付须要频繁更新 UI 的长任务,可以利用 requestAnimationFrame 来分解任务。这样可以在浏览器的重绘周期内实行任务,确保流畅的动画效果。节流节流是一种限定函数在一定韶光内只能实行一次的技能。它常日用于处理高频率的事宜,确保在指定的韶光间隔内只实行一次目标函数。常见利用场景:滚动事宜处理、窗口调度大小事宜(与防抖结合利用)、定时更新数据(如 API 要求)等。防抖防抖是一种确保某个函数在一定韶光内只被调用一次的技能。它常日用于处理用户输入事宜,确保在用户停滞输入后再实行某个操作。常见利用场景:输入框的实时搜索建议、窗口调度大小事宜、表单提交按钮的防止重复点击等。2.2.2.3 React专项React18引入了useTransition和useDeferredValue两个钩子,用于管理渲染性能,特殊是在并发模式下。
React19 操持引入“自动影象化”,即:不用手动编写 useMemo useCallback memo 来进行性能优化,通过全新编译器,React 19 可以自动检测组件的状态变革,并智能地决定是否要重新渲染。
hooksuseCallback / useMemouseCallback / useMemo 都是为了优化性能而设计的Hooks,它们可以帮助我们在组件重新渲染时避免不必要的打算或函数创建一样平常useMemo用来缓存值,useCallback用来缓存函数,不再赘述。详情自行参考文档:useMemo[5]、useCallback[6]。useTransition(React18)许可利用者标记一些状态更新为次要更新(non-urgent updates),从而让这些更新在用户交互停息期间实行。这样可以避免由于大量数据更新导致的UI卡顿,提高运用的相应性。useDeferredValue(React18)与 useTransition 类似,但是它专门用于延迟某些值的变革,直到当前事情完成。这常日用于列表滚动或者其他须要立即相应的情形,比如滚动一个长列表时,希望在滚动结束后再更新某些值。memomemo 是一个高阶组件(Higher-Order Component,HOC),它用于优化纯函数组件的性能。紧张浸染是在组件的props未发生改变时避免不必要的重新渲染,从而提高运用的性能。FragmentFragment 许可利用者将子元素列表分组,而无需添加额外的DOM节点到终极渲染的HTML构造中。可以用于简化 DOM构造,减少 DOM嵌套。优化列表渲染(Key)React 可以利用 key 对列表渲染进行优化,key 的紧张浸染是帮助 React 标识哪个元素已被添加、移除或改变,从而使得 React 能够更高效地更新 DOM。精确利用 key 属性可以在 React 渲染大量列表时提高性能并减少内存花费。其余 Key 也可以用在非列表场景,比如:动态组件、条件渲染、HOC等。相应式加载参考 2.2.4 HTML代码性能优化--为图像和***供应不同来源。实质便是不同尺寸屏幕加载不同体历年夜小的图片,根据实际情形按需加载,不摧残浪费蹂躏带宽。load="lazy"loading="lazy" 属性值表示该图片该当利用可以通过网络自行研究用法。
3.1 chrome自带剖析工具
3.1.1 performance面板用于剖析测试网页性能。3.1.2 lighthouse面板用于剖析测试网页性能。3.1.3 network面板用于查看网页网络资源加载情形。3.1.4 性能数据剖析面板(即将被移除)用于剖析测试网页性能,但即将弃用。3.2 三方测评站点
用于剖析测试网页性能。
3.2.1 pagespeed3.2.2 webpagetest3.3 webpack剖析插件
Webpack Bundle Analyzer用于剖析 Webpack 构建输出的工具。它能够帮助开拓者更好地理解构建产物(bundle)的组成,包括各个模块、库和资源文件的大小分布情形。Source Map Explore用于剖析 JavaScript 源代码大小及其在打包后(如利用 Webpack 打包后的 bundle 文件)所占比例的工具。umi,analyze=1umi内置剖析产物构成体积分布方案。3.4 VSCode 插件
Bundle Size用于实时查看 Webpack 构建产物大小的插件。四、总结
本文先容了一些常见的性能优化策略以及用于调试优化效果的性能剖析工具。我们在实际性能优化过程中,可以对自己要优化的目标项目进行剖析,然后采取适宜的策略去办理详细问题,末了用性能剖析工具去验证优化效果。前端技能在持续发展,性能优化策略也会与时俱进。我们可以大胆考试测验,小心求证。
路漫漫其修远兮,吾辈高下而求索.
参考链接:
[1]https://www.npmjs.com/package/umi-plugin-runtime-import
[2]https://www.npmjs.com/package/umi-plugin-runtime-import-v4
[3]https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Using_web_workers
[4]https://developer.mozilla.org/en-US/docs/Web/API/WebGPU_API
[5]https://zh-hans.react.dev/reference/react/useMemo
[6]https://zh-hans.react.dev/reference/react/useCallback
[7]https://ahooks.js.org/zh-CN/hooks/use-request/cache#swr
[8]https://github.com/alibaba/hooks/blob/master/packages/hooks/src/useRequest/src/utils/cache.ts
[9]https://github.com/umijs/qiankun/issues/1555
[10]https://www.yuque.com/kuitos/gky7yw/gs4okg
[11]https://css-tricks.com/css-sprites/
[12]https://developer.mozilla.org/zh-CN/docs/Web/CSS/background-position