欢迎来到飞鸟慕鱼博客,开始您的技术之旅!
当前位置: 首页知识笔记正文

前端面试 性能优化,前端性能优化的实践

终极管理员 知识笔记 104阅读

行优化 一、白屏时间 FCPFirst Contentful Paint

白屏时间即用户点击一个链接或打开浏览器输入URL地址后从屏幕空白到显示第一个画面的时间。

二、白屏时间的重要性

当用户点开一个链接或者是直接在浏览器中输入URL开始进行访问时就开始等待页面的展示。页面渲染的时间越短用户等待的时间就越短用户感知到页面的速度就越快。这样可以极大的提升用户的体验减少用户的跳出提升页面的留存率。

三、白屏的过程

从输入url到页面的画面展示的过程

1、首先在浏览器地址栏中输入url

2、浏览器先查看浏览器缓存-系统缓存-路由器缓存如果缓存中有会直接在屏幕中显示页面内容。若没有则跳到第三步操作。

3、在发送http请求前需要域名解析(DNS解析)解析获取相应的IP地址。

4、浏览器向服务器发起tcp连接与浏览器建立tcp三次握手。

5、握手成功后浏览器向服务器发送http请求请求数据包。

6、服务器处理收到的请求将数据返回至浏览器

7、浏览器收到HTTP响应

8、读取页面内容浏览器渲染解析html源码

9、生成Dom树、解析css样式、js交互,渲染显示页面

浏览器下载HTML后首先解析头部代码进行样式表下载然后继续向下解析HTML代码构建DOM树同时进行样式下载。当DOM树构建完成后立即开始构造CSSOM树。理想情况下样式表下载速度够快DOM树和CSSOM树进入一个并行的过程当两棵树构建完毕构建渲染树然后进行绘制。

Tips:浏览器安全解析策略对解析HTML造成的影响

当解析HTML时遇到内联JS代码会阻塞DOM树的构建会先执行完JS代码;当CSS样式文件没有下载完成时浏览器解析HTML遇到了内联JS代码此时浏览器暂停JS脚本执行暂停HTML解析。直到CSS文件下载完成完成CSSOM树构建重新恢复原来的解析。

JavaScript 会阻塞 DOM 生成而样式文件又会阻塞 JavaScript 的执行所以在实际的工程中需要重点关注 JavaScript 文件和样式表文件使用不当会影响到页面性能的。

四、白屏-性能优化 1. DNS解析优化

针对DNS Lookup环节我们可以针对性的进行DNS解析优化。

DNS缓存优化DNS预加载策略稳定可靠的DNS服务器

DNS缓存优化是一种提高网络性能和减少延迟的技术。DNSDomain Name System是将域名转换为IP地址的系统它在互联网中起到了重要的作用。当我们访问一个网站时计算机需要向DNS服务器查询该域名对应的IP地址然后才能建立连接。
DNS缓存优化的目标是减少DNS查询的次数从而加快网页加载速度。以下是一些常见的DNS缓存优化方法

本地DNS缓存操作系统和浏览器通常会在本地缓存最近查询的DNS记录。这样当再次访问相同的域名时就可以直接从本地缓存中获取IP地址而无需进行DNS查询。
DNS服务器缓存DNS服务器也会缓存最近查询的DNS记录。当多个用户查询相同的域名时DNS服务器可以直接返回缓存的结果而无需再次查询。TTL设置每个DNS记录都有一个TTLTime-to-Live值表示该记录在缓存中的有效时间。通过设置适当的TTL值可以控制DNS记录在缓存中的存储时间。较短的TTL值可以使DNS记录更频繁地更新从而及时获取最新的IP地址。DNS负载均衡一些网站使用多个IP地址来提供服务并通过DNS负载均衡将流量分散到不同的服务器上。这样可以减轻单个服务器的负载并提高响应速度。CDNContent Delivery NetworkCDN是一种分布式网络架构它将网站的内容缓存在全球各地的服务器上。当用户访问网站时CDN会根据用户的地理位置选择最近的服务器提供内容从而减少网络延迟。
通过使用这些DNS缓存优化方法可以显著提高网页加载速度和用户体验。

DNS预加载是一种优化网页加载速度的策略它通过在浏览器中预先解析域名的IP地址以减少DNS查询的时间延迟。以下是几种常见的DNS预加载策略

<link reldns-prefetch href...>在HTML文档的头部添加标签使用rel属性设置为dns-prefetch并在href属性中指定要预加载的域名。浏览器会在加载页面时提前解析这些域名的IP地址。
示例
<head><link reldns-prefetch href reldns-prefetch href  HTTP响应头服务器可以在HTTP响应头中添加Link字段指示浏览器预加载特定域名的DNS信息。
示例
Link: </assets/styles.css>; relpreload; asstyle,</assets/script.js>; relpreload; asscript,</api/data>; relpreload; asfetch
DNS预解析在CSS样式表中使用import或url()函数引用外部资源时浏览器会自动进行DNS预解析。
import url(  

需要注意的是DNS预加载并不适用于所有情况它主要适用于那些在页面加载过程中需要进行大量DNS查询的情况。在使用DNS预加载时应谨慎选择需要预加载的域名避免过度预加载导致不必要的网络请求。此外不同浏览器对DNS预加载的支持程度可能有所不同因此在使用时需要进行兼容性测试。

2. TCP网络链路优化 调整TCP窗口大小TCP窗口大小决定了在发送数据之后需要等待确认的时间。通过增大TCP窗口大小可以提高网络吞吐量和传输速度。但是过大的窗口大小可能导致网络拥塞因此需要根据网络状况进行调整。使用拥塞控制算法TCP拥塞控制算法用于检测网络拥塞并调整发送速率。常见的拥塞控制算法包括TCP Reno、TCP Cubic等。选择适合网络环境的拥塞控制算法可以提高网络的稳定性和吞吐量。启用快速重传和快速恢复快速重传和快速恢复是TCP的一种机制用于快速恢复丢失的数据包而不必等待超时。通过启用这些机制可以减少数据传输的延迟和丢包的影响。启用Selective AcknowledgmentSACKSACK是一种TCP扩展允许接收方向发送方报告丢失的数据段从而避免不必要的重传。启用SACK可以提高网络的吞吐量和传输效率。使用TCP加速器或优化器TCP加速器或优化器是一种网络设备或软件用于优化TCP连接的性能。它们可以通过压缩数据、缓存重复数据、优化传输路径等方式来提高网络性能。
使用带宽管理工具带宽管理工具可以帮助控制网络流量优化带宽分配和流量控制。通过合理管理带宽可以提高网络的稳定性和性能。

这些是一些常见的TCP网络链路优化策略可以根据具体的网络环境和需求选择适合的优化方法。同时网络优化是一个复杂的过程需要综合考虑多个因素并进行实验和测试来评估优化效果。

3. 服务端处理优化 代码优化对服务端代码进行优化包括减少不必要的计算、避免重复操作、使用高效的算法和数据结构等。优化代码可以减少CPU和内存的使用提高代码执行效率。并发处理使用多线程、多进程或异步处理等技术充分利用服务器的多核处理能力提高并发处理能力和吞吐量。合理地划分任务和资源避免竞争条件和阻塞提高系统的响应速度。数据库优化对数据库进行优化包括合理设计数据库结构、使用索引、优化查询语句、缓存查询结果等。减少数据库的访问次数和查询时间提高数据库的读写性能。缓存优化使用缓存技术将频繁访问的数据存储在内存中减少对后端存储系统的访问。可以使用内存缓存如Redis、Memcached或分布式缓存如CDN、分布式缓存系统来提高数据访问速度。负载均衡使用负载均衡技术将请求分发到多个服务器上避免单个服务器过载。可以使用硬件负载均衡器或软件负载均衡器来实现负载均衡提高系统的可扩展性和稳定性。异步处理将耗时的操作如文件读写、网络请求转为异步处理避免阻塞主线程。可以使用异步框架、消息队列等技术来实现异步处理提高系统的并发能力和响应速度。定期优化和监控定期对服务端进行性能分析和监控识别瓶颈和性能问题并进行相应的优化。可以使用性能分析工具、日志分析工具等来帮助定位和解决问题。

这些是一些常见的服务端处理优化策略可以根据具体的应用场景和需求选择适合的优化方法。同时优化是一个持续的过程需要不断地进行测试、评估和调整以达到最佳的性能和用户体验。

4. 浏览器下载、解析、渲染页面优化

根据浏览器对页面的下载、解析、渲染过程可以考虑一下的优化处理

尽可能的精简HTML的代码和结构尽可能的优化CSS文件和结构一定要合理的放置JS代码尽量不要使用内联的JS代码将渲染首屏内容所需的关键CSS内联到HTML中能使CSS更快速地下载。在HTML下载完成之后就能渲染了页面渲染的时间提前从而缩短首屏渲染时间延迟首屏不需要的图片加载而优先加载首屏所需图片offsetTop<clientHeight
document.documentElement.clientHeight//获取屏幕可视区域的高度element.offsetTop//获取元素相对于文档顶部的高度

因为JavaScript 会阻塞 DOM 生成而样式文件又会阻塞 JavaScript 的执行所以在实际的工程中需要重点关注 JavaScript 文件和样式表文件使用不当会影响到页面性能的。

实际开发中优化首屏时间可用的技术手段 1. SSR渲染服务端渲染

SSR渲染是指服务器端渲染Server-Side Rendering的过程。传统的Web应用通常使用客户端渲染Client-Side Rendering的方式即在浏览器中使用JavaScript动态生成页面内容。而SSR渲染则是将页面的初始渲染过程从客户端转移到服务器端。
在SSR渲染中服务器端会在接收到客户端请求时动态生成完整的HTML页面并将其发送给客户端。这样客户端在接收到HTML页面后可以直接显示内容而不需要等待客户端渲染完成。这种方式可以减少页面加载时间和白屏时间提高用户体验。
SSR渲染的过程通常包括以下步骤
客户端发送请求到服务器端。
服务器端接收到请求并根据请求的路由信息确定要渲染的页面。
服务器端获取页面所需的数据可以通过调用API、查询数据库等方式获取数据。
服务器端将获取到的数据注入到页面模板中生成完整的HTML页面。
服务器端将生成的HTML页面发送给客户端。
客户端接收到HTML页面后可以直接显示内容而不需要等待客户端渲染完成。
客户端在接收到HTML页面后可以继续执行JavaScript代码处理交互逻辑和动态更新页面。
通过使用SSR渲染可以提高页面的加载速度和用户体验特别是对于首次访问页面的用户。然而SSR渲染也会增加服务器的负载和响应时间因此在实施SSR时需要进行适当的性能优化和资源管理。

2. 骨骼图减少白屏时间提高用户体感和留存

前端骨骼图Skeleton Screen是一种在页面加载过程中展示页面结构的技术。它通过在页面加载时先展示一个简单的骨架结构然后逐渐填充内容给用户一种页面正在加载的感觉。
前端骨骼图的主要作用是改善用户体验减少页面加载时的白屏时间。以下是前端骨骼图的几个作用
提示页面正在加载前端骨骼图可以向用户传达页面正在加载的信息让用户知道他们的操作已经被响应并且页面即将显示。

减少白屏时间通过展示页面的大致结构前端骨骼图可以减少页面加载时的白屏时间。即使页面内容尚未完全加载用户也可以看到页面的大致布局给予他们一种页面正在加载的感觉。提高用户满意度前端骨骼图可以提高用户的满意度因为他们可以立即看到页面的结构而不需要等待页面完全加载。提示用户交互元素位置通过展示页面的骨架结构前端骨骼图可以帮助用户快速定位和识别页面中的交互元素提高用户的操作效率。

总的来说前端骨骼图可以改善用户体验减少页面加载时的不适感提高用户满意度和页面的可用性。它是一种简单而有效的技术可以在页面加载过程中给用户提供更好的反馈和体验。

3. 流式渲染Streaming Rendering

流式渲染Streaming Rendering是一种渲染页面的技术它允许在服务器端逐步生成和发送页面内容给客户端而不需要等待整个页面完全渲染完成。

传统的页面渲染方式是等待服务器端生成完整的HTML页面然后一次性将整个页面发送给客户端。这种方式在页面内容较多或复杂时会导致较长的白屏时间用户需要等待较长时间才能看到页面内容。
而流式渲染则是在服务器端逐步生成页面内容并将其逐段发送给客户端。这样客户端可以在接收到部分内容后就开始渲染和显示页面而不需要等待整个页面完全加载。
流式渲染的优势包括
1.减少白屏时间通过逐步发送页面内容流式渲染可以减少白屏时间让用户更快地看到页面内容。
2. 提高用户体验用户可以在页面渲染的过程中进行交互而不需要等待整个页面加载完成。这可以提高用户的满意度和页面的可用性。
2. 节省带宽和资源流式渲染只需要发送页面的部分内容可以减少网络传输的数据量节省带宽和服务器资源。
3. 适应性更强流式渲染可以根据网络状况和设备性能动态调整发送的内容以提供更好的用户体验。
流式渲染的实现通常涉及使用适当的技术和框架如服务器端渲染SSR、HTTP分块传输、WebSockets等。通过合理地划分页面内容和使用适当的渲染策略可以实现流式渲染并提供更好的用户体验。

4. 如果一个列表有 100000 个数据这个该怎么进行展示 1. 将数据分页利用分页的原理每次服务器端只返回一定数目的数据浏览器每次只对一部分进行加载。 2. 使用懒加载的方法每次加载一部分数据其余数据当需要使用时再去加载。 3. 虚拟列表每次只渲染需要视口的部分 什么是虚拟列表

虚拟列表Virtual List是一种优化大型列表渲染性能的技术。它通过只渲染可见区域内的列表项而不是渲染整个列表来减少页面渲染的开销。
虚拟列表的作用是提高列表的性能和用户体验特别是在处理大量数据时。传统的列表渲染方式会将所有列表项都渲染到DOM中无论其是否可见。这会导致页面加载缓慢、滚动卡顿等问题。而虚拟列表只渲染可见区域内的列表项可以大大减少DOM操作和渲染开销提高页面的响应速度和流畅度。
虚拟列表的用法通常涉及以下几个方面
… 列表项的高度或平均高度以便计算可见区域的范围。
… 列表项的数量以便根据可见区域的范围计算需要渲染的列表项。
… 列表项的渲染方式通常是通过动态创建和销毁DOM元素来实现。
… 列表项的滚动事件以便在滚动时更新可见区域的范围并触发列表项的渲染。
虚拟列表的具体实现方式可以根据使用的前端框架或库而有所不同。一些流行的前端框架如React、Vue等提供了相应的虚拟列表组件或插件可以方便地实现虚拟列表的功能。
总的来说虚拟列表是一种优化大型列表渲染性能的技术通过只渲染可见区域内的列表项来提高页面的响应速度和流畅度。它在处理大量数据时非常有用并且可以与各种前端框架和库结合使用。

虚拟列表原理

虚拟列表的原理是通过动态渲染可见区域内的列表项而不是渲染整个列表。它基于以下两个核心概念

可见区域范围计算虚拟列表需要计算出当前可见区域的起始索引和结束索引。这可以通过列表容器的高度、列表项的高度或平均高度以及滚动位置来确定。根据这些参数可以计算出当前可见区域内的列表项数量和索引范围。动态渲染根据可见区域的索引范围虚拟列表只渲染可见区域内的列表项。当用户滚动列表时虚拟列表会根据滚动位置和可见区域范围的变化动态地创建或销毁列表项的DOM元素。这样只有当前可见区域内的列表项才会被渲染到页面上而不会渲染整个列表。

虚拟列表的实现通常涉及以下步骤

初始化计算可见区域的范围并渲染初始的可见区域内的列表项。滚动事件监听监听列表容器的滚动事件当滚动发生时触发更新可见区域的操作。更新可见区域根据滚动位置和列表项的高度或平均高度计算出新的可见区域的范围。根据新的可见区域范围动态地创建或销毁列表项的DOM元素。渲染列表项根据可见区域的索引范围渲染可见区域内的列表项。这可以通过使用虚拟DOM或其他渲染技术来实现。
通过以上步骤虚拟列表可以在滚动时动态地渲染可见区域内的列表项从而提高页面的渲染性能和用户体验。
需要注意的是虚拟列表的实现方式可能因使用的前端框架或库而有所不同。一些流行的前端框架如React、Vue等提供了相应的虚拟列表组件或插件可以方便地实现虚拟列表的功能。 react实现虚拟列表使用react库

在React中可以使用一些库或组件来实现虚拟列表的功能。其中react-window 和 react-virtualized 是两个常用的库它们提供了虚拟列表的组件和功能。

下面是使用 react-window 实现虚拟列表的基本步骤

安装 react-window 库
npm install react-window
导入所需的组件和函数
import { FixedSizeList } from react-window;
创建列表项组件
const ListItem  ({ index, style }) > {  // 根据索引获取列表项的数据  const item  data[index];  return (    <div style{style}>      {/* 渲染列表项的内容 */}      <p>{item.title}</p>    </div>  );};
渲染虚拟列表组件
const VirtualList  () > {  return (    <FixedSizeList      height{400} // 列表容器的高度      width{300} // 列表容器的宽度      itemCount{data.length} // 列表项的总数      itemSize{50} // 列表项的高度    >      {ListItem} // 列表项组件    </FixedSizeList>  );};

在上述代码中FixedSizeList 组件是 react-window 提供的虚拟列表组件它接收一些必要的属性如列表容器的高度、宽度列表项的总数和高度等。ListItem 组件则是自定义的列表项组件根据索引获取对应的数据并渲染列表项的内容。
通过以上步骤就可以使用 react-window 实现一个简单的虚拟列表。你可以根据实际需求进行进一步的定制和优化例如添加滚动事件监听、动态加载数据等。
请注意以上代码仅为示例实际使用时需要根据具体情况进行适当的修改和调整。

原生Js实现虚拟列表 创建列表容器元素
<div idlist-container styleheight: 400px; overflow-y: scroll;></div>
获取列表容器和列表项的相关信息
const listContainer  document.getElementById(list-container);const itemHeight  50; // 列表项的高度const totalItems  1000; // 列表项的总数
渲染可见区域内的列表项
function renderVisibleItems() {  const scrollTop  listContainer.scrollTop;  const startIndex  Math.floor(scrollTop / itemHeight);  const endIndex  Math.min(startIndex  Math.ceil(listContainer.clientHeight / itemHeight), totalItems);  for (let i  startIndex; i < endIndex; i) {    const listItem  document.createElement(div);    listItem.style.height  itemHeight  px;    listItem.textContent  Item   i;    listContainer.appendChild(listItem);  }}
监听列表容器的滚动事件并在滚动时更新可见区域的列表项
listContainer.addEventListener(scroll, renderVisibleItems);

通过以上步骤就可以实现一个简单的原生虚拟列表。在滚动时会根据可见区域的范围动态地创建和销毁列表项从而提高性能和用户体验。
需要注意的是以上代码仅为示例实际使用时需要根据具体情况进行适当的修改和调整。例如可以添加数据加载、缓存机制等来优化列表的性能。

4. 使用数组分块技术基本思路是为要处理的项目创建一个队列然后设置定时器每过一段时间取出一部分数据然后再使用定时器取出下一个要处理的项目进行处理接着再设置另一个定时器。 5. 怎么进行站点内的图片性能优化

在类电商类项目往往存在大量的图片如 banner 广告图菜单导航图美团等商家列表头图等。图片众多以及图片体积过大往往会影响页面加载速度造成不良的用户体验所以对图片进行优化势在必行。

如果页面启动时加载了几十张图片甚至更多而这些图片请求几乎是并发的在 Chrome 浏览器最多支持的并发请求次数是有限的其他的请求会推入到队列中等待或者停滞不前直到上轮请求完成后新的请求才会发出。所以相当一部分图片资源请求是需要排队等待时间的过多的图片必然会影响页面的加载和展示

选择合适的图片格式 JPEG

JPEG 是由 Joint Photographic Experts Group 所开发出的一种图片。
它最大的特点是 有损压缩
这种高效的压缩算法使它成为了一种非常轻巧的图片格式。
另一方面即使被称为“有损”压缩JPG 的压缩方式仍然是一种高质量的压缩方式当我们把图片体积压缩至原有体积的 50% 以下时JPG 仍然可以保持住 60% 的品质。
此外JPG 格式以 24 位存储单个图可以呈现多达 1600 万种颜色足以应对大多数场景下对色彩的要求这一点决定了它压缩前后的质量损耗并不容易被我们人类的肉眼所察觉。

优点 JPEG 格式的图片可以呈现数百万种颜色。所以每当网站需要呈现色彩丰富的图片JPEG 总是最佳选择。有损压缩你可以通过压缩大大的减少图片的体积一般图片用 60%级别比较合适如果选择大于 75%的压缩等级则会使图片有明显的质量下降。无兼容性问题所以开发者可以放心随意使用。 使用场景 JPG 适用于呈现色彩丰富的图片在我们日常开发中JPEG 图片经常作为大的背景图、轮播图或 Banner 图出现。但是有损压缩后的图片确实很容易露出马脚当它处理矢量图形和 Logo 等线条感较强、颜色对比强烈的图像时人为压缩的图片模糊会相当明显。JPEG 图像不支持透明度处理透明图片可选择使用 PNG。 PNG

PNG可移植网络图形格式是由 W3C 开发的图片格式是一种无损压缩的高保真的图片格式。它同时支持 8 位和 24 位这里都是二进制数的位数。按照我们前置知识里提到的对应关系8 位的 PNG 最多支持 256 种颜色而 24 位的可以呈现约 1600 万种颜色。

PNG 图片具有比 JPEG 更强的色彩表现力对线条的处理更加细腻对透明度有良好的支持。它弥补了上文我们提到的 JPEG 的局限性唯一的缺点就是 体积太大

应用场景 PNG 在处理线条和颜色对比度方面的优势我们主要用它来呈现小的 Logo、颜色简单且对比强烈的图片或背景等。支持透明度处理透明图片可选择使用 PNG GIF

GIF 是一种最多支持 256 种颜色的 8 位无损图片格式。这个限制让 GIF 格式对于多颜色或者摄影图片的展示无能为力。

优点 支持 256 种颜色文件体积通常都很小支持透明 应用场景 支持动画适合去展示一些无限循环的动画比如图标、表情、广告栏等。对于一些只有简单色彩的图片非常合适。 SVG

SVGScalable Vector Graphics是一种基于XML的矢量图形格式用于描述二维图形和图像。与位图图像如JPEG、PNG不同SVG使用数学公式来描述图形因此可以无损地缩放和放大而不会失真。
SVG图像由一系列的矢量图形元素组成如路径path、矩形rect、圆形circle、椭圆ellipse、线条line、多边形polygon等。这些元素可以通过属性来定义其位置、大小、颜色、填充等样式。
SVG具有以下特点和优势

矢量图形SVG图像是基于数学公式的矢量图形可以无损地缩放和放大而不会失真。这使得SVG非常适合在不同尺寸和分辨率的设备上显示如高清屏幕、移动设备等。小文件大小由于SVG使用文本格式存储图形数据相对于位图图像SVG图像通常具有较小的文件大小这有助于减少网络传输和页面加载时间。
可编辑性SVG图像可以通过文本编辑器进行编辑和修改可以添加、删除或修改图形元素和属性使其更具交互性和动态性。动画和交互性SVG支持动画和交互效果可以通过CSS和JavaScript来实现图形的动态变化、交互操作和响应。可搜索和可索引由于SVG图像是基于文本的搜索引擎可以读取和索引其中的文本内容从而提高网页的可搜索性和可访问性。

SVG广泛应用于Web开发、数据可视化、图标设计、动画制作等领域它提供了一种灵活、可扩展和高质量的图形解决方案。

WebP

WebP 是一种同时提供了有损压缩与无损压缩可逆压缩的图片文件格式派生自影像编码格式 VP8。它像 JPEG 一样对细节丰富的图片信手拈来像 PNG 一样支持透明像 GIF 一样可以显示动态图片集多种图片文件格式的优点于一身。

WebP 最初在 2010 年发布目标是减少文件大小但达到和 JPEG 格式相同的图片质量希望能够减少图片档在网络上的发送时间。根据 Google 较早的测试WebP 的无损压缩比网络上找到的 PNG 档少了 45的文件大小即使这些 PNG 档在使用 pngcrush 和 PNGOUT 处理过WebP 还是可以减少 28的文件大小。

虽然 webP 有诸多优点但是它不能完全替代 JPEG 和 PNG因为浏览器对 WebP 支持并不普遍。特别是移动端 IOS 系统基本不支持。

AVIF

目前最新的图片格式是AVIFAV1 Image File Format。AVIF是一种基于AV1视频编解码器的图像格式它使用先进的压缩算法来提供更高的图像质量和更小的文件大小。
AVIF格式具有以下优点

更高的压缩效率相比于JPEG和WebP等传统的图像格式AVIF可以提供更高的压缩效率从而在相同的图像质量下减小文件大小。更好的图像质量AVIF支持更高的色彩深度和更广的色域范围可以提供更好的图像质量和更准确的颜色表示。动态范围AVIF支持高动态范围HDR图像可以呈现更丰富的色彩和更高的对比度。透明度支持与WebP和PNG等格式类似AVIF也支持透明度通道可以实现图像的透明效果。
尽管AVIF具有许多优点但由于它是一种相对较新的格式目前还不被所有的浏览器和图像编辑软件广泛支持。因此在使用AVIF格式时需要确保目标平台和设备支持该格式或者提供备用的图像格式作为兼容性方案。 图片压缩 一张图片加载过程

1.发起请求当浏览器解析HTML文档时遇到标签或CSS中的background-image属性时会发起对图片资源的请求。浏览器会根据src属性或url()函数中指定的图片路径向服务器发送请求。
2.服务器响应服务器接收到浏览器的请求后会返回对应的图片资源。服务器的响应时间取决于网络连接的速度和服务器的性能。
3.下载图片一旦浏览器接收到服务器的响应它会开始下载图片。下载过程中浏览器会根据网络状况和带宽限制以及服务器的响应速度逐步接收图片的数据。
4. 图片解码当图片的数据完全下载到浏览器后浏览器会对图片进行解码。解码过程将图像数据转换为像素以便在屏幕上显示。
5.图片渲染一旦图片解码完成浏览器会将像素数据渲染到屏幕上的相应位置。图片的渲染过程包括将像素绘制到屏幕上的像素点并根据CSS样式和布局进行相应的调整和显示。
加载完成当图片渲染完成后浏览器会触发load事件表示图片加载完成。此时可以通过JavaScript等方式对图片进行进一步的操作。

需要注意的是图片加载过程中可能会受到网络状况、服务器响应速度、图片大小等因素的影响。优化图片加载的方法包括使用适当的图片格式、压缩图片大小、使用懒加载等技术以提高页面加载速度和用户体验。

图片众多以及图片体积过大往往会影响页面加载速度造成不良的用户体验有部分图片达到几百 kB甚至 2M直接导致了加载时间过长。所以对于体积过大的图片在保持图片在可接受的清晰度范围内可适当对图片大小进行压缩。

图片压缩又分为有损压缩无损压缩

有损压缩

有损压缩指在压缩文件大小的过程中损失了一部分图片的信息也即降低了图片的质量即图片被压糊了并且这种损失是不可逆的。常见的有损压缩手段是按照一定的算法将临近的像素点进行合并。压缩算法不会对图片所有的数据进行编码压缩而是在压缩的时候去除了人眼无法识别的图片细节。因此有损压缩可以在同等图片质量的情况下大幅降低图片的体积。例如 jpg 格式的图片使用的就是有损压缩。

无损压缩

无损压缩指的是在压缩图片的过程中图片的质量没有任何损耗。我们任何时候都可以从无损压缩过的图片中恢复出原来的信息。压缩算法对图片的所有的数据进行编码压缩能在保证图片的质量的同时降低图片的体积。例如 png、gif 使用的就是无损压缩。

工具压缩 tinypng 免费、批量、速度块智图压缩 免费、批量、好用squoosh 在线图片压缩工具compressor 支持 JPG、PNG、SVG、GIF webpack 压缩

工程化的项目可以在 webpack 里面配置 image-webpack-loader 进行图片压缩

安装依赖
npm install --save-dev image-webpack-loader
配置 webpack
module.exports  {...  module: {    rules: [      {        test: /.(png|jpe?g|gif|svg)(?.*)?$/,        use: [          {            loader: file-loader,            options: {              name: [name].[hash:7].[ext]            },          },          {            loader: image-webpack-loader,            options: {              mozjpeg: {                progressive: true,                quality: 50,              },              optipng: {                enabled: true,              },              pngquant: {                quality: [0.5, 0.65],                speed: 4,              },              gifsicle: {                interlaced: false,              },              webp: { // 不支持WEBP就不要写这一项                quality: 75              },            },          },        ],      },    ],  },}

至于要不要使用插件自动压缩就见仁见智了因为有些 UI 和产品会说压缩出来的效果图片不是他们想要的。

使用雪碧图

雪碧图CSS Sprites国内也叫 CSS 精灵是一种 CSS 图像合成技术主要用于小图片显示。

浏览器请求资源的时候同源域名请求资源的时候有最大并发限制chrome 为 6 个就比如你的页面上有 10 个相同 CDN 域名小图片那么需要发起 10 次请求去拉取分两次并发。第一次并发请求回来后发起第二次并发。如果你把 10 个小图片合并为一张大图片的画那么只用一次请求即可拉取下来 10 个小图片的资源。减少服务器压力减少并发减少请求次数。

优点:

把诸多小图片合成一张大图利用 backround-position 属性值来确定图片呈现的位置可以有效的较少请求个数而且而不影响开发体验使用构建插件可以做到对开发者透明。适用于页面图片多且丰富的场景。

缺点:

生成的图片体积较大减少请求个数同时也增加了图片大小不合理拆分将不利于并行加载。

合成雪碧图

在 webpack 中有相应的插件提供了自动合成雪碧图的功能并且可以自动生成对应的样式文件—— webpack-spritesmith使用方法如下:

var path  require(path)var SpritesmithPlugin  require(webpack-spritesmith)module.exports  {  // ...  plugins: [    new SpritesmithPlugin({      src: {        cwd: path.resolve(__dirname, src/ico),        glob: *.png,      },      target: {        image: path.resolve(__dirname, src/spritesmith-generated/sprite.png),        css: path.resolve(__dirname, src/spritesmith-generated/sprite.styl),      },      apiOptions: {        cssImageRef: ~sprite.png,      },    }),  ],}

通过上面配置就能将 src/ico 目录下的所有 png 文件合成雪碧图并且输出到对应目录同时还可以生成对应的样式文件样式文件的语法会根据你配置的样式文件的后缀动态生成。

使用 iconfont

iconfont(字体图标)即通过字体的方式展示图标多用于渲染图标、简单图形、特殊字体等。

优点

像使用字体一样设置大小、颜色及其他样式不失真轻量易修改有效减少 HTTP 请求次数
推荐使用阿里的字体图标库iconfont 使用 base64 格式

**原理**将图片转换为 base64 编码字符串 inline 到页面或 css 中。

优点

提升性能: 网页上的每一个图片都是需要消耗一个 http 请求下载而来的, 图片的下载始终都要向服务器发出请求要是图片的下载不用向服务器发出请求base64 可以随着 HTML 的下载同时下载到本地.减少 https 请求。

加密: 让用户一眼看不出图片内容 , 只能看到编码。

方便引用: 在多个文件同时使用某些图片时, 可以把图片转为 base64 格式的文件, 把样式放在全局中, 比如 common.css, 以后在用的时候就可以直接加类名, 二不需要多层找文件路径, 会提升效率

但需要注意的是如果图片较大图片的色彩层次比较丰富则不适合使用这种方式因为该图片经过 base64 编码后的字符串非常大会明显增大 HTML 页面的大小从而影响加载速度。

base64 化最常见的就是在 url-loader 中使用。

module.exports  {...  module: {    rules: [      {        test: /.(png|jpe?g|gif|svg)(?.*)?$/,        loader: url-loader,        options: {          limit: 10240,          name: utils.assetsPath(img/[name].[hash:7].[ext]),        }      },    ],  },}

这样就能将项目中小于 10kb 的图片转化为 base64 应用到页面中

使用 css 代替图片

比如实现修饰效果如半透明、边框、圆角、阴影、渐变等在当前主流浏览器中都可以用 CSS 达成这样能减少图片的请求达到优化的目的。

缺点:

受限于 css 的浏览器的兼容性对于较复杂的图案就无能为力了写也麻烦开发成本大 使用 CDN 图片

CDN 的全称是 Content Delivery Network即内容分发网络。CDN 是构建在网络之上的内容分发网络依靠部署在各地的边缘服务器通过中心平台的负载均衡、内容分发、调度等功能模块使用户就近获取所需内容降低网络拥塞提高用户访问响应速度和命中率。CDN 的关键技术主要有内容存储和分发技术。

举个简单的例子

以前买火车票大家都只能去火车站买后来我们买火车票就可以在楼下的火车票代售点买了。

基本原理

CDN 的基本原理是广泛采用各种缓存服务器将这些缓存服务器分布到用户访问相对集中的地区或网络中在用户访问网站时利用全局负载技术将用户的访问指向距离最近的工作正常的缓存服务器上由缓存服务器直接响应用户请求。

基本思路

CND 的基本思路是尽可能避开互联网上有可能影响数据传输速度和稳定性的瓶颈和环节使内容传输的更快、更稳定。通过在网络各处放置节点服务器所构成的在现有的互联网基础之上的一层智能虚拟网络CDN 系统能够实时地根据网络流量和各节点的连接、负载状况以及到用户的距离和响应时间等综合信息将用户的请求重新导向离用户最近的服务节点上。其目的是使用户可就近取得所需内容解决 Internet 网络拥挤的状况提高用户访问网站的响应速度。

CDN 的优势 CDN 节点解决了跨运营商和跨地域访问的问题访问延时大大降低大部分请求在 CDN 边缘节点完成CDN 起到了分流作用减轻了源站的负载。 图片懒加载

懒加载是一种网页性能优化的方式它能极大的提升用户体验。图片一直是影响网页性能的主要元凶现在一张图片超过几兆已经是很经常的事了。如果每次进入页面就请求所有的图片资源那么可能等图片加载出来用户也早就走了。所以进入页面的时候只请求可视区域的图片资源。

总结出来就是

减少资源的加载页面启动只加载首屏的图片这样能明显减少了服务器的压力和流量也能够减小浏览器的负担。防止并发加载的资源过多而阻塞 js 的加载影响整个网站的启动影响用户体验浪费用户的流量有些用户并不想全部看完全部加载会耗费大量流量。 原理

图片懒加载的原理就是暂时不设置图片的 src 属性而是将图片的 url 隐藏起来比如先写在 data-src 里面等当前图片是否到了可视区域再将图片真实的 url 放进 src 属性里面从而实现图片的延迟加载。

function lazyload() {  let viewHeight  document.body.clientHeight //获取可视区高度  let imgs  document.querySelectorAll(img[data-src])  imgs.forEach((item, index) > {    if (item.dataset.src  ) return    // 用于获得页面中某个元素的左上右和下分别相对浏览器视窗的位置    let rect  item.getBoundingClientRect()    if (rect.bottom > 0 && rect.top < viewHeight) {      item.src  item.dataset.src      item.removeAttribute(data-src)    }  })}// 可以使用节流优化一下window.addEventListener(scroll, lazyload)

通过上面例子的实现我们要实现懒加载都需要去监听 scroll 事件尽管我们可以通过函数节流的方式来阻止高频率的执行函数,但是我们还是需要去计算 scrollTop,offsetHeight 等属性有没有简单的不需要计算这些属性的方式呢答案是有的—IntersectionObserver

IntersectionObserver

IntersectionObserver是一个用于监测目标元素与其祖先元素或视窗viewport之间交叉状态的API。它提供了一种异步的、高性能的方法来观察元素是否进入或离开视窗或者与其祖先元素发生交叉。
使用IntersectionObserver可以实现以下功能

监测元素的可见性可以观察元素是否进入或离开视窗以便在元素可见或不可见时执行相应的操作。实现懒加载可以延迟加载图片、视频或其他资源只有当它们进入视窗时才进行加载从而提高页面加载速度和性能。实现无限滚动可以在滚动时动态加载更多的内容当滚动到特定位置时触发加载新数据的操作。监测元素与其祖先元素的交叉状态可以观察元素与其祖先元素之间的交叉状态例如元素是否完全进入祖先元素、部分进入或完全离开。 使用IntersectionObserver的优势包括 异步执行IntersectionObserver使用异步的方式进行观察不会阻塞主线程从而提高页面的响应性能。高性能IntersectionObserver使用浏览器内部的优化机制可以高效地检测元素的交叉状态减少不必要的计算和重复操作。简化代码相比于传统的滚动事件监听和计算元素位置的方式IntersectionObserver提供了更简洁、易于使用的API减少了开发者的工作量。
总之IntersectionObserver是一个强大的API可以帮助开发者实现各种与元素可见性和交叉状态相关的功能提升用户体验和页面性能。
const imgs  document.querySelectorAll(img[data-src])const config  {  rootMargin: 0px,  threshold: 0,}let observer  new IntersectionObserver((entries, self) > {  entries.forEach((entry) > {    if (entry.isIntersecting) {      let img  entry.target      let src  img.dataset.src      if (src) {        img.src  src        img.removeAttribute(data-src)      }      // 解除观察      self.unobserve(entry.target)    }  })}, config)imgs.forEach((image) > {  observer.observe(image)})
图片预加载

图片预加载是指在一些需要展示大量图片的网站将图片提前加载到本地缓存中从而提升用户体验。

常用的方式有两种一种是隐藏在 css 的 background 的 url 属性里面一种是通过 javascript 的 Image 对象设置实例对象的 src 属性实现图片的预加载。

1. 用 CSS 和 JavaScript 实现预加载
<!DOCTYPE html><html><head>  <style>    .preload-image {      display: none;      background-image: url(    }  </style>  <script>    function preloadImage(url) {      const img  new Image();      img.src  url;    }    // 预加载图片    preloadImage(  </script></head><body>  <div classpreload-image></div></body></html>

在上面的代码中我们首先在 标签中定义了一个 CSS 样式使用 .preload-image 类来设置预加载图片的背景图。这个元素默认是隐藏的因为我们使用了 display: none;。
然后在

2. 使用 JavaScript 实现预加载
function preloadImage(url) {  return new Promise((resolve, reject) > {    const img  new Image();    img.onload  () > resolve(img);    img.onerror  () > reject(new Error(图片加载失败));    img.src  url;  });}// 预加载图片的 URL 数组const imageUrls  [       存储预加载的图片对象const preloadedImages  [];// 遍历图片 URL 数组逐个进行预加载imageUrls.forEach(url > {  preloadImage(url)    .then(img > {      preloadedImages.push(img);      console.log(图片 ${url} 预加载完成);    })    .catch(error > {      console.error(图片 ${url} 预加载失败: ${error.message});    });});

在上面的代码中preloadImage 函数接受一个图片的 URL返回一个 Promise 对象。在 Promise 的 resolve 回调中我们将加载完成的图片对象传递给 resolve 函数在 reject 回调中我们将加载失败的错误信息传递给 reject 函数。
然后我们定义了一个图片 URL 数组 imageUrls以及一个用于存储预加载图片对象的数组 preloadedImages。
接下来我们使用 forEach 方法遍历图片 URL 数组并逐个调用 preloadImage 函数进行预加载。在 then 回调中我们将加载完成的图片对象存储到 preloadedImages 数组中并输出预加载完成的消息在 catch 回调中我们输出加载失败的消息。
这样当所有图片都预加载完成后preloadedImages 数组中将包含所有预加载的图片对象。

响应式图片加载

什么是响应式图片加载其实就是在不同分辨率的设备上显示不同尺寸的图片避免资源的浪费。

常用的方法就是 css3 的媒体查询(media query)。

media  screen and (min-width: 1200px) {  img {    background-image: url(1.png);  }}media  screen and (min-width: 992px) {  img {    background-image: url(2.png);  }}media  screen and (min-width: 768px) {  img {    background-image: url(3.png);  }}media screen and (min-width: 480px) {  img {    background-image: url(4.png);  }}

此外还可以使用 HTML5 的 picture 属性进行响应式处理。方法如下

创建 picture 标签。放置多个 source 标签以指定不同的图像文件名进而根据不同的条件进行加载。添加一个回退的元素
<picture>  <source srcsetsrc/img/l.png media(min-width: 1200px) />  <source srcsetsrc/img/2.png media(min-width: 992px) />  <source srcsetsrc/img/4.png media(min-width: 768px) />  <img srcsrc/img/4.png /></picture>

需要注意的是现在很多浏览器对于 picture 这个标签还不支持使用的时候需要加以注意。

渐进式图片

渐进式图片的意思是在高画质图像加载完之前会先显示低画质版本。低画质版本由于画质低、压缩率高尺寸很小加载很快。在两者之间我们也可以根据需要显示不同画质的版本。

渐进式图片可以让用户产生图片加载变快的印象。用户不再盯着一片空白区域等待图片加载而能看到图像变得越来越清晰这样对用户体验也是友好的。

骨架屏技术也是类似的原理。

总结 选择合适的图片格式和压缩大图可从根源上截图大图加载过慢的问题。使用雪碧图iconfontbase64css 代替图片等可减少图片 http 请求提高页面加载速度。使用 CDN 图片可达到分流的效果减少服务券压力。图片懒加载预加载渐进式图片等可不同程度减少白屏时间提高产品体验。 6. DNS 预解析是什么怎么实现 DNS优化

在介绍dns-prefetch之前先要提下当前对于DNS优化主流方法。
一般来说一次DNS解析需要耗费 20-120ms所以为了优化DNS我们可以考虑两个方向

减少DNS请求次数缩短DNS解析时间dns-prefetch 什么是dns-prefetch

dns-prefetch(DNS预获取)是前端网络性能优化的一种措施。它根据浏览器定义的规则提前解析之后可能会用到的域名使解析结果缓存到系统缓存中缩短DNS解析时间进而提高网站的访问速度。

为什么要用dns-prefetch

每当浏览器从第三方服务器发送一次请求时都要先通过DNS解析将该跨域域名解析为 IP地址然后浏览器才能发出请求。

如果某一时间内有多个请求都发送给同一个服务器那么DNS解析会多次并且重复触发。这样会导致整体的网页加载有延迟的情况。

我们知道虽然DNS解析占用不了多大带宽但是它会产生很高的延迟尤其是对于移动网络会更为明显。

因此为了减少DNS解析产生的延迟我们可以通过dns-prefetch预解析技术有效地缩短DNS解析时间。

<link reldns-prefetch href 
dns-prefetch背后原理

当浏览器访问一个域名的时候需要解析一次DNS获得对应域名的ip地址。 在解析过程中按照:

浏览器缓存系统缓存路由器缓存ISP(运营商)DNS缓存根域名服务器顶级域名服务器主域名服务器

的顺序逐步读取缓存直到拿到IP地址。

dns-prefetch就是在将解析后的IP缓存在系统中。

这样dns-prefetch就有效地缩短了DNS解析时间。因为在本地操作系统做了DNS缓存使得DNS在解析的过程中提前在系统缓存中找到了对应IP。

这样一来 后续的解析步骤就不用执行了进而也就缩短了DNS解析时间。

假如浏览器首次将一个域名解析为IP地址并缓存至操作系统那么下一次DNS解析时间可以低至0-1ms

倘若结果不缓存在系统那么就需要读取路由器的缓存进而后续的解析时间最小也要约15ms

如果路由器缓存也不存在则需要读取ISP运营商DNS缓存一般像taobao.com、baidu.com这些常见的域名读取ISP运营商DNS缓存需要的时间在80-120ms如果是不常见的域名平均需要200-300ms

一般来说大部分的网站到运营商这块都能找到IP。

那也就是说dns-prefetch可以给DNS解析过程带来15-300ms的提升尤其是一些大量引用很多其他域名资源的网站提升效果就更加明显了

浏览器DNS缓存与dns-prefetch

现代浏览器为了优化DNS解析也设有了浏览器DNS缓存。

每当在首次DNS解析后会对其IP进行缓存。至于缓存时长每种浏览器都不一样比如Chrome的过期时间是1分钟在这个期限内不会重新请求DNS。

Tip:

每当Chrome浏览器启动的时候就会自动的快速解析浏览器最近一次启动时记录的前10个域名。所以经常访问的网址就不存在DNS解析的延迟进而打开速度更快。

而dns-prefetch 相当于在浏览器缓存之后在本地操作系统中做了DNS缓存个人理解为的是给浏览器缓存做保障一般来说DNS在系统的缓存时间是大于浏览器的。

浏览器与系统DNS缓存时间

TTL(Time-To-Live)就是一条域名解析记录在DNS服务器中的存留时间

浏览器DNS缓存的时间跟DNS服务器返回的TTL值无关, 它的缓存时间取决于浏览器自身设置。

系统缓存会参考DNS服务器响应的TTL值但是不完全等于TTL值。

国内和国际上很多平台的TTL值都是以秒为单位的很多的默认值都是3600也就是默认缓存1小时。

dns-prefetch缺点

dns-prefetch最大的缺点就是使用它太多。

过多的预获取会导致过量的DNS解析对网络是一种负担。

最佳实践

请记住以下三点

dns-prefetch 仅对跨域域上的 DNS查找有效因此请避免使用它来指向相同域。
DNS预获取只对跨域域名有效是因为当浏览器加载网页时它会自动解析同一域名下的资源的DNS记录。因此使用DNS预获取来指向相同域名下的资源是没有意义的因为浏览器已经在加载网页时自动解析了这些资源的DNS记录。
另外使用DNS预获取也可能会增加额外的网络请求从而增加网页加载时间。因此如果要使用DNS预获取最好将其用于跨域域名以最大程度地提高网页加载性能。

除了使用HTML的标签来指定DNS预获取还可以通过HTTP链接字段将其指定为HTTP标头。这可以通过在HTTP响应头中添加Link字段来实现。
下面是一个示例展示如何在HTTP响应头中使用Link字段来指定DNS预获取

Link: </example-domain.com>; reldns-prefetch

在上面的示例中</example-domain.com>是要预获取的域名reldns-prefetch表示这是一个DNS预获取的链接关系。
通过将DNS预获取指定为HTTP标头可以在浏览器请求网页时一起获取DNS记录从而加快网页加载速度。这种方法适用于所有资源不仅仅是HTML页面。
需要注意的是使用HTTP链接字段来指定DNS预获取需要在服务器端进行配置以确保正确的HTTP响应头被发送到浏览器。

考虑将 dns-prefetch 与 preconnect(预连接)提示配对。
将DNS预获取dns-prefetch与预连接preconnect提示配对是一种优化网页加载性能的常见做法。这两个技术可以一起使用以减少网络延迟并加快网页加载速度。
DNS预获取用于在浏览器加载网页时提前解析域名的DNS记录以减少DNS查找的延迟。而预连接则用于在浏览器加载网页时提前建立与服务器的连接以减少建立连接的延迟。
通过将这两个技术配对使用可以在浏览器加载网页时同时进行DNS解析和建立连接的操作从而进一步减少加载时间。
下面是一个示例展示如何在HTML中同时使用DNS预获取和预连接:
<link reldns-prefetch href//example-domain.com><link relpreconnect href//example-domain.com>

在上面的示例中dns-prefetch指定了要预获取的域名preconnect指定了要预连接的域名。通过将这两个标签添加到HTML中浏览器将在加载网页时同时进行DNS预获取和预连接的操作。
需要注意的是不是所有的域名都适合进行DNS预获取和预连接。只有在确实需要加载来自特定域名的资源时才应该使用这些优化技术。此外使用预连接时还需要确保服务器支持HTTP/2或HTTP/3协议以获得最佳效果。

7. 在 React 中可以做哪些性能优化

使用 shouldComponentUpdate 避免不需要的渲染但是如果对 props 和 state 做深比较代价很大所以需要根据业务进行些取舍在有子组件的情况下为了避免子组件的重复渲染可以通过父组件来判断子组件是否需要 PureRender。

将 props 设置为数组或对象每次调用 React 组件都会创建新组件就算传入的数组或对象的值没有改变他们的引用地址也会发生改变比如如果按照如下的写法那么每次渲染时 style 都是一个新对象

// 不推荐<button style{{ color: red }} />// 推荐const style  { color: red }<button style{style} />// 不推荐<button style{this.props.style || {} } />  // 推荐const defaultStyle  {}<button style{this.props.style || defaultStyle } />   

将props设置为数组或对象的好处是可以确保每次渲染时都创建一个新的对象即使传入的数组或对象的值没有改变。这样做的好处有以下几点

避免副作用在React中组件的渲染应该是纯粹的不应该有副作用。如果在组件的渲染过程中修改了传入的props对象可能会导致意外的行为和难以调试的问题。通过每次渲染时创建一个新的对象可以确保props对象的不可变性避免副作用。引用比较React在进行虚拟DOM的比较时会使用浅比较shallow comparison来判断是否需要重新渲染组件。如果传入的props对象是同一个引用地址即使对象的值没有改变React也无法判断是否需要重新渲染组件。通过每次渲染时创建一个新的对象可以确保每次都有一个新的引用地址从而使React能够正确地判断是否需要重新渲染组件。性能优化虽然每次渲染时创建新的对象可能会增加一些开销但在大多数情况下这种开销是可以忽略不计的。而通过确保props对象的不可变性可以帮助React进行更精确的比较和优化从而提高组件的性能。

需要注意的是如果在父组件中频繁地创建新的数组或对象作为props传递给子组件可能会导致子组件频繁地重新渲染。在这种情况下可以考虑使用React.memo或shouldComponentUpdate等优化技术来避免不必要的重新渲染。

将函数的绑定移动到构造函数内可以避免每次都绑定事件。使用 immutable 不可变数据在我们项目中使用引用类型时为了避免对原始数据的影响一般建议使用 shallowCopy 和 deepCopy 对数据进行处理但是这样会造成 CPU 和 内存的浪费所以推荐使用 immutable优点如下 降低了“可变”带来的复杂度节省内存immutable 使用结构共享尽量复用内存没有被引用的对象会被垃圾回收可以更好的做撤销/重做复制/粘贴时间旅行不会有并发问题因为数据本身就是不可变的拥抱函数式编程 给子组件设置一个唯一的 key因为在 diff 算法中会用 key 作为唯一标识优化渲染 8. 前端性能优化指标有哪些怎么进行性能检测 1. 概述

web性能说简单点就是网站打开速度快不快页面中的动画够不够流畅表单提交的速度是否够快列表滚动页面切换是否卡顿。性能优化就是让网站变得快。

在MDN上对web性能的定义是网站或应用程序的客观度量和可感知的用户体验。比如减少页面加载事件(减少文件体积减少HTTP请求使用预加载)让网站尽快可用(懒加载或者分片加载)平滑的交互性(使用CSS替代JS动画减少UI重绘)感知表现(加载动画loading等给用户感觉快)性能测定(性能指标性能测试性能监控以便持续优化毕竟性能优化是个持续的过程)。

页面性能关乎到用户的留存网站的转换率用户体验和网站的传播甚至影响搜索排名遭到用户投诉当然也会影响开发的效率。

2. 性能指标

进行性能优化之前首先要知道要在哪些方面做性能优化。

首先需要了解性能指标多快的速度才算快呢可以使用专业的工具可量化的评估出网站或应用的性能表现。

立足于网站页面响应的生命周期分析出造成较差性能表现的原因最后进行技术改造可行性分析等具体的优化措施持续迭代优化就可以了。

事实上性能是相对的他并不是绝对的概念。对于一个用户而言在不同的网络环境下访问页面的速度可能是不同的。即使相同的网站在懒加载的情况下也会显得快。

在讨论性能的时候精确地可量化的指标是很重要的。但是仅仅因为一个度量标准是基于客观准备并且可以定量的度量的并不一定意味这些度量是有用的。对于Web开发人员来说如何恒量一个Web页面的性能一直都是一个难题。

最初开发人员使用Time to To Byte。DomContentLoaded和Load这些恒量文档加载进度的指标但他们不能直接反应用户视觉体验。

为了恒量用户视觉体验Web标准中定义了一些性能指标。这些性能指标被各大浏览器标准化实现例如First Paint和First Contentful Paint。

还有一些由Web孵化器社区组提出的性能指标如Largest COntentful Paint, Time to Interactive, First Input Delay, First CPU Idle。

另外还有Google提出的First Meaningful Paint, Speed Index。

百度提出的First Screen Paint。

这些指标之间并不是毫无关联而是在以用户为中心的目标中不断演进出来的有的已经不再建议使用有的被各种测试工具实现有的则可以作为通用标准可用于生产环境测量的API。

3. RAIL性能模型

RAIL是ResponseAnimationIdle和Load的首字母缩写是一种由Google Chrome团队于2015年提出的性能模型用于提升浏览器的用户体验和性能。

RAIL模型的理念是以用户为中心最终目标并不是让你的网站在任何特定设备上都能运行很快而是使用户满意。

Response: 应该尽可能快速的响应用户的操作应在在100ms以内响应用户输入。

Animation: 在展示动画的时候每一帧应该以16ms进行渲染这样可以保持动画效果的一致性并且避免卡顿。

Idle: 当使用js主线程的时候应该把任务划分到执行时间小于50ms的片段中去这样可以释放线程以进行用户交互。50ms为单位是为了保证用户在发生操作的100ms内做出响应。

要使网站响应迅速动画流畅通常都需要较长的处理时间但以用户为中心来看待性能问题就会发现并非所有工作都需要在响应和加载阶段完成完全可以利用浏览器的空闲时间处理可延迟的任务只要让用户感受不到延迟即可。利用空闲时间处理延迟可减少预加载的数据大小以保证网站或应用快速完成加载。

Load: 应该在小于1s的时间内加载完成你的网站并可以进行用户交互。根据网络条件和硬件的不同用户对性能延迟的理解也有所不同在3G网络需要花费更多的时间5s是一个更现实的目标。

基于用户体验的性能指标其中包括一下几个比较重要的性能指标。

1. FCP (First Contentful Paint)

首次内容绘制浏览器首次绘制来自DOM的内容的时间内容必须包括文本图片非白色的canvas或svg也包括带有正在加载中的web字体文本。这是用户第一次看到的内容。

2. LCP (Largest Contentful Paint)

最大内容绘制可视区域中最大的内容元素呈现到屏幕上的时间用以估算页面的主要内容对用户的可见时间。img图片video元素的封面通过url加载到的北京文本节点等为了提供更好的用户体验网站应该在2.5s以内或者更短的时间最大内容绘制。

3. FID (First Input Delay)

首次输入延迟从用户第一次与页面进行交互到浏览器实际能够响应该交互的时间输入延迟是因为浏览器的主线程正忙于做其他事情所以不能响应用户发生这种情况的一个常见原因是浏览器正忙于解析和执行应用程序加载的大量计算的JavaScript。

4. TTI (Time to Interactive)

网页第一次完全达到可交互状态的时间点浏览器已经可以持续的响应用户的输入完全达到可交互的状态的时间是在最后一个长任务完成的时间并且在随后的5s内网络和主线程是空闲的。从定义上来看中文名称叫持续可交互时间或可流畅交互时间更合适。

5. TBT (Total Block Time)

总阻塞时间度量了FCP和TTI之间的总时间在该时间范围内主线程被阻塞足够长的时间以防止输入响应。只要存在长任务该主线程就会被视为阻塞该任务在主线程上运行超过50毫秒。

线程阻塞是因为浏览器无法中断正在进行的任务因此如果用户确实在较长的任务中间与页面进行交互则浏览器必须等待任务完成才能响应。

6. CLS (Cumulative Layout Shift)

累计布局位移CLS会测量在页面整个生命周期中发生的每个意外的布局移位的所有单独布局移位分数的总和他是一种保证页面的视觉稳定性从而提升用户体验的指标方案。

用人话来说就是当点击页面中的某个元素的时候突然布局变了手指点到了其它位置。比如想点击页面的链接突然出现了一个banner。这种情况可能是因为尺寸未知的图像或者视频。页面抖动

4. Web Vitals

这也是谷歌指定的web性能指标标准, 谷歌认为之前的标准太复杂指标太多了在2020年重新进行了梳理简化到了三个。加载性能LCP交互性FID视觉稳定性CLS。只需要做好这三个网站的性能基本上就可以了。

测量Web Vitals的工具有很多比如Lighthouseweb-vitals浏览器插件web vitals。

1. Web-Vitals
// npm install web-vitals -gimport { getLCP, getFID, getCLS } from web-vitals;getLCP(conole.log)getFID(conole.log)getCLS(conole.log)
2. 浏览器插件

谷歌浏览器可以直接在插件市场中查找并且安装web vitals。安装完成之后浏览器的右上角会多出插件标志点击就会显示页面的性能指标。
如图

5. 性能测试

性能检测是作为性能优化过程中的一环他的目的通常是给后续优化工作提供指导方向参考基线以及千户对比的依据。性能检测并不是一次性执行结束后就完成的工作他会在检测记录和改进的迭代过程中不断重复。来协助网站的性能优化不断接近期望的效果。

1. Lighthouse灯塔

Lighthouse是谷歌开发并开源的web性能测试工具用于改进网络应用的质量可以将其作为一个Chrome扩展程序运行或从命令行运行。只需要为其提供一个需要审查的地址Lighthouse就会对页面进行一连串的测试生成一个有关页面性能的报告。

在浏览器的调试工具中默认就存在lighthouse选项只需要切换至lighthouse在右侧的选项区选中需要的选项。点击生成报告。

2. WebPageTest

在线web性能测试工具( 提供多地点测试。他只能测试已经发布了的网站。输入需要测试的网页地址点击start test按钮就开始测试了可以选择测试地理位置测试的浏览器等。

6. Chrome DevTools 1. 浏览器的任务管理器

可以查看当前Chrome浏览器中所有进程关于GPU网络和内存空间的使用情况这些进程包括当前打开的各个标签页安装的各种扩展插件以及GPU网络渲染等浏览器的默认进程通过监控这些数据可以定位可能存在内存泄露或网络资源加载异常的问题进程。

更多工具 -> 任务管理器

可以看到所有进行的进程可以看到内存占用网络消耗。

2. Network网络分析

Network面板是一个常被用到的工具通过它可以获取到网站所有资源的请求情况包括加载时间尺寸大小优先级设置以及HTTP缓存等信息。可以帮助开发者发现可能由于未进行有效压缩而导致资源尺寸过大的问题未配置缓存策略导致二次请求加载时间过长的问题。

缓存测试
Disable cache吞吐测试模拟网速Coverage
监控并统计出网站应用运行过程中代码执行的覆盖率情况。
统计的对象是JavaScript脚本文件与css样式文件统计结果主要包括文件的字节大小执行过程中已覆盖的代码字节数可视化的覆盖率条形图。
根据执行结果可以发现到底哪些尺寸较大的代码文件覆盖率较低这就意味着这些代码文件中可能存在较多的无用代码。
Ctrl shift p 搜索 coverage 就会显示出来。
可以看到第一个文件有58%没有被使用到第二个有95.2%没有使用到。Memory 面板
主要用于分析内存占用情况如果出现内存泄露那么就可能带来网站崩溃的后果。
为了更细致和准确的监控应用网站当前的内存使用情况Chrome浏览器提供Memory面板可以快速生成当前的堆内存快照。

结束后可以查看到内存占用大小就可以对对应的模块进行优化。

Performance
使用Performance面板主要对网站应用的运行时性能表现进行检测和分析包括页面的每秒帧数CPU的消耗和各种请求花费的时间。
点击开始后等待两三秒就可以停止了。
这里面就可以统计出网站的信息。FPS
另一个非常方便的工具是FPS计数可以在页面运行时提供对FPS的实时估计。
Ctrl Shift P 输入 fps 选择显示渲染。就会在浏览器中出现监控面板。
还可以使用性能监视器这是一个事实的监视器。
Ctrl Shift P 输入 monitor

标签:
声明:无特别说明,转载请标明本文来源!