性能优化与调试技巧 | 青训营

62 阅读8分钟

在现代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请求减少之间的收益)
  • 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的;
    • gzip压缩:nginx配置中可以开启,资源传输体积压缩变小,相应会增加服务器压缩和浏览器资源解压的压力;对于图片资源压缩效率不明显;
    • Terser 等工具是 Javascript 资源压缩混淆的神器。对代码层进行处理,比如:
      • 1、长变量名替换短变量;
      • 2、删除空格换行符;
      • 3、预计算能力;
      • 4、移除无法被执行的代码;
      • 5、移除无用的变量及函数
    • js、css、html资源压缩
  • 2)Tree Shaking技术
    Tree Shaking: 无用导出将在生产环境进行删除,到达减少资源体积的效果;

3、网络优化

  • 1)CND:就近原则
  • 2)Http2.0
  1. 多路复用,在浏览器可并行发送 N 条请求。
  2. 首部压缩,更小的负载体积。
  3. 请求优先级,更快的关键请求

其他

  • 路由懒加载
  • 第三方组件按需加载
  • ···

避免多次修改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是一款在线性能分析工具,可以帮助我们测试网站在不同网络条件下的加载速度、渲染速度、响应时间等。它提供了多个测试服务器,可以根据不同的测试需求选择相应的测试服务器。

综上所述,前端性能优化是一个综合性的工作,需要结合多个方面的优化策略来实现。通过减少重绘和重排、使用节流和防抖技术、使用性能分析工具、懒加载和预加载、代码分割和模块化,以及合理使用缓存等方法,我们可以有效地提高网站的性能,提供更好的用户体验。不断学习和实践这些技巧,将有助于成为一名优秀的前端工程师。