在现代Web开发中,前端性能优化是至关重要的一部分。用户对于页面加载速度和响应性的期望越来越高,因此我们需要采取一系列的策略来提高网站的性能。本文将讨论如何通过优化JavaScript代码来提高性能,包括减少重绘和重排、使用节流和防抖技术,以及使用性能分析工具等关键技巧。
优化JavaScript代码可以显著提高性能和用户体验:
-
减少重绘和重排:重绘和重排是性能消耗较大的操作,可以通过以下方式来减少: ①使用 CSS 动画代替 JavaScript 动画,因为 CSS 动画更有效率。 ②批量更新 DOM,避免频繁的单独更新,可以使用 DocumentFragment 或虚拟 DOM 来优化。 ③ 避免频繁获取样式信息(比如使用 offsetTop、offsetLeft 等),可以将这些信息缓存起来。
-
使用节流和防抖技术:可以通过限制事件触发的频率来优化性能,避免过多的计算和渲染: ①节流技术可以控制事件触发的频率,在固定时间间隔内只执行一次。常见的实现方式是使用 setTimeout 或 requestAnimationFrame 来延迟执行回调函数。 ②防抖技术可以在事件触发后延迟一段时间再执行回调函数,如果在延迟时间内再次触发了同类型事件,则重新计时延迟时间。可以使用 clearTimeout 和 setTimeout 来实现。
-
使用性能分析工具:使用性能分析工具可以帮助我们找出代码中的性能瓶颈和优化空间,常见的性能分析工具有: ①Chrome 开发者工具中的 Performance 面板,可以记录和分析页面加载和执行过程中的性能数据。 ②Lighthouse,一个由 Google 提供的开源工具,可以对网页进行全面的性能分析和优化建议。 ③WebPageTest,可以模拟不同网络条件下的页面加载速度,并提供详细的性能分析报告。
前端性能优化分两部分
1、加载性能优化
2、渲染性能优化
一、加载性能优化
本质:
- 1、减少请求次数;
- 2、减少请求资源的大小;
- 3、网络优化;
1、减少请求次数
为什么减少请求次数?
浏览器能够并行发出请求,但是每次并行发出请求的个数是有限制的,以chrome为例:
- 同一域名下,同一GET请求的并发数是1,也就是说上一个请求结束,才会执行下一个请求,否则置入队列等待发送;
- 同一域名下,不同GET/POST请求的并发数量是6。当发送的请求数量达到6个,并且都没有得到响应时,后面的请求会置入队列等待发送。
所以资源请求数过多肯定比请求数少更耗时,直接影响网页的加载速度;
减少请求次数方式
- 1)图片资源
-
- CSS雪碧图技术
把一些常用、重复使用的小图合并成一张大图,使用的时候通过背景图片定位(background-position),定位到具体的某一张小图上;
1、UI给图;
2、webpack插件:webpack-spritesmith - 图片懒加载
视区外图片先不加载,当进入视区或者进入视区之前的某个位置加载;
1、css的loading属性;
2、getBoundingClientRect方法,获取dom元素的top、left、bottom、right、height、width信息,对比视区大小,进行图片加载(需要结合节流);
3、IntersectionOberser方法,能够监听元素是否到达当前视口的事件; - 字体图标
一个图标字体比一系列图像要小,一旦图标字体加载了,图标就会马上渲染出来,不需要下载一个图像,可以减少HTTP请求。 - base64编码
图片的base64编码就是可以将一张图片数据编码成一串字符串,使用该字符串代替图像地址url;
(均衡css体积增大和http请求减少之间的收益)
- CSS雪碧图技术
- 2)合理利用缓存
-
- 避免一行代码修改导致整个 bundle 的缓存失效
- 浏览器缓存(资源)
强缓存
协商缓存 - DNS缓存(DNS查找时间)
- 分包加载 (Bundle Spliting)
- 3)合并CSS和JS文件
将CSS和JavaScript文件合并为单独的文件。合并CSS和JavaScript文件是减少HTTP请求数量和提高网站加载速度的有效方法;
2、减少资源大小
相同网络环境下,更小体积意味着传输速度更快;
减少资源大小方式
-
1)资源压缩
-
- 图片压缩工具:tinyPng等
- 图片格式:,
webp普遍比jpeg/png更小,而avif又比webp小一个级别
如何鉴别浏览器是否支持webp? -
- 通过canvas来判断(这个比较常用),创建一个canvas元素,然后把它转成
image/webp格式的data_url,如果这个data_url里面包含webp,则代表当前浏览器支持webp格式, 反之则不支持:document.createElement('canvas').toDataURL('image/webp').indexOf('data:image/webp') - 在服务端根据请求header信息判断浏览器是否支持webp:在图片请求发出的时候,Request Headers 里有 Accept,服务端可以根据Accept 里面是否有 image/webp 进行判断。
- 通过加载一张 webp 图片进行判断:先加载一个WebP图片,如果能获取到图片的宽度和高度,就说明是支持WebP的;
- 通过canvas来判断(这个比较常用),创建一个canvas元素,然后把它转成
- gzip压缩:nginx配置中可以开启,资源传输体积压缩变小,相应会增加服务器压缩和浏览器资源解压的压力;对于图片资源压缩效率不明显;
- Terser 等工具是 Javascript 资源压缩混淆的神器。对代码层进行处理,比如:
-
- 1、长变量名替换短变量;
- 2、删除空格换行符;
- 3、预计算能力;
- 4、移除无法被执行的代码;
- 5、移除无用的变量及函数
- js、css、html资源压缩
-
2)Tree Shaking技术
Tree Shaking: 无用导出将在生产环境进行删除,到达减少资源体积的效果;
3、网络优化
- 1)CND:就近原则
- 2)Http2.0
- 多路复用,在浏览器可并行发送 N 条请求。
- 首部压缩,更小的负载体积。
- 请求优先级,更快的关键请求
其他
- 路由懒加载
- 第三方组件按需加载
- ···
避免多次修改DOM样式:
-
javascriptCopy code // 不推荐的写法 const element = document.getElementById('myElement'); element.style.width = '100px'; element.style.height = '100px'; // 推荐的写法 const element = document.getElementById('myElement'); element.style.cssText = 'width: 100px; height: 100px;'; -
使用
class而不是直接操作style属性: -
javascriptCopy code // 不推荐的写法 const element = document.getElementById('myElement'); element.style.color = 'red'; // 推荐的写法 const element = document.getElementById('myElement'); element.classList.add('red-text'); -
缓存布局信息,减少重排次数:
-
javascriptCopy code // 不推荐的写法 for (let i = 0; i < 1000; i++) { const element = document.getElementById('myElement'); console.log(element.offsetTop); } // 推荐的写法 const element = document.getElementById('myElement'); const offsetTop = element.offsetTop; for (let i = 0; i < 1000; i++) { console.log(offsetTop); }
节流和防抖技术:
-
节流(Throttling):
-
javascriptCopy code function throttle(func, delay) { let timerId; return function() { if (!timerId) { timerId = setTimeout(() => { func.apply(this, arguments); timerId = null; }, delay); } } } window.addEventListener('scroll', throttle(function() { console.log('Scroll event'); }, 200)); -
防抖(Debouncing):
-
javascriptCopy code function debounce(func, delay) { let timerId; return function() { clearTimeout(timerId); timerId = setTimeout(() => { func.apply(this, arguments); }, delay); } } const input = document.getElementById('myInput'); input.addEventListener('input', debounce(function() { console.log('Input event'); }, 500));
性能分析工具:
-
Chrome开发者工具:Chrome的开发者工具可以帮助我们检查代码执行时间、内存使用情况、网络请求等,十分方便。在使用过程中,我们可以使用Performance面板来查看性能分析信息。同时,还可以使用Memory和Network面板来监控内存和网络请求。
-
JSLint和JSHint:JSLint和JSHint是两个质量工具,可以帮助我们检查JavaScript代码中的错误和潜在问题。在检查过程中,还可以自定义配置文件,以帮助我们更好地发现问题和优化代码。
-
YSlow:YSlow是Yahoo出品的一款性能优化工具,可以帮助我们评估网站的性能,并给出相应的建议。在使用过程中,它会根据一系列的规则来检查网站的性能,并给出一些改进建议。
-
Firebug:Firebug是Firefox浏览器的一款插件,可以帮助我们查看JavaScript代码的执行速度、内存使用情况等。它还可以检查页面的HTML、CSS、JavaScript、网页结构、网络请求等。
-
WebPageTest:WebPageTest是一款在线性能分析工具,可以帮助我们测试网站在不同网络条件下的加载速度、渲染速度、响应时间等。它提供了多个测试服务器,可以根据不同的测试需求选择相应的测试服务器。
综上所述,前端性能优化是一个综合性的工作,需要结合多个方面的优化策略来实现。通过减少重绘和重排、使用节流和防抖技术、使用性能分析工具、懒加载和预加载、代码分割和模块化,以及合理使用缓存等方法,我们可以有效地提高网站的性能,提供更好的用户体验。不断学习和实践这些技巧,将有助于成为一名优秀的前端工程师。