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

283 阅读4分钟

前言

性能优化和调试技巧对于提高网站和应用程序的运行速度和响应能力来讲是十分重要的。本次文章我们主要通过优化JavaScript代码来提高性能,以及如何使用性能分析工具进行调试:

简介

性能优化的目标是在不影响功能的完整性和性能的前提下,减少程序或网站在运行时的资源消耗,提高运行效率。采取一系列策略和技术来提高程序或网站的执行速度、响应速度和资源利用率,从而提高用户体验,简单来说就是降本增效。 性能优化的主要关注点包括:

1.加载速度:优化页面加载速度。

2.响应速度:优化页面和程序的响应速度,以便用户能够更快地获得所需的信息和结果。

3.资源利用率:减少程序对计算资源和带宽的消耗,以提高运行效率和降低成本。

4.可维护性和可扩展性:确保代码易于维护和扩展,以适应不断变化的需求和环境。

详细技巧

  1. 减少重绘(Repaints)和重排(Reflows): 重绘和重排是浏览器渲染过程中的两个重要阶段。减少重绘和重排可以提高页面的性能。 下面是一些优化建议
  • 使用CSS属性transformopacityfilter进行动画和过渡,因为它们不会触发重绘和重排。
  • 将DOM操作和样式更改合并成单个操作,以减少浏览器需要处理的重绘和重排次数。
  • 尽可能减少使用JavaScript动态改变样式,改为使用CSS样式表。

示例 使用transform属性进行动画

const element = document.getElementById('animated-element');
let rotation = 0;

function animate() {
  requestAnimationFrame(animate);
  rotation += 1;
  element.style.transform = `rotate(${rotation}deg)`;
}

animate();

  1. 使用节流(Throttling)和防抖(Debouncing)技术:

节流和防抖技术可以用于降低函数的执行频率,从而提高性能。

  • 节流:确保函数在指定的时间间隔内最多执行一次。这可以防止短时间内频繁触发函数。
  • 防抖:在函数被高频率触发时,只有当用户停止触发函数一段时间后才执行函数。这可以防止短时间内多次执行函数。

示例 使用lodash库的_.throttle方法实现节流:

const _ = require('lodash');

function handleWindowResize() {
  console.log('Window resized');
}

window.addEventListener('resize', _.throttle(handleWindowResize, 200));

使用lodash库的_.debounce方法实现防抖:

const _ = require('lodash');

function handleKeyup(event) {
  console.log('Keyup detected:', event.target.value);
}

document.getElementById('input-element').addEventListener('keyup', _.debounce(handleKeyup, 300));

  1. 使用请求动画帧(requestAnimationFrame):

requestAnimationFrame是一个替代传统的setTimeoutsetInterval的方法,用于创建平滑的动画效果。它可以让浏览器在合适的时机执行动画,从而提高性能。

示例 使用请求动画帧(requestAnimationFrame)实现平滑动画

const element = document.getElementById('animated-element');

function animate(timestamp) {
  if (timestamp === undefined) {
    timestamp = performance.now();
  }

  const elapsed = timestamp - prevTimestamp;
  prevTimestamp = timestamp;

  const distance = elapsed * 50; // Move 50px per second
  element.style.left = `${position + distance}px`;

  if (position < 300) {
    requestAnimationFrame(animate);
  }
}

const prevTimestamp = performance.now();
let position = 0;

requestAnimationFrame(animate);

  1. 使用Web Workers:

Web Workers允许在后台线程中运行JavaScript代码,以避免阻塞主线程。这对于执行计算密集型任务或处理大量数据的场景非常有用。

示例 创建一个简单的Web Workers

// worker.js
self.addEventListener('message', ({data: inputData}) => {
  const result = processData(inputData);
  postMessage({result});
});

function processData(data) {
  // Heavy computation goes here...
}

在主线程中实现Web Workers

// main.js
const worker = new Worker('worker.js');

worker.postMessage(someData);

worker.onmessage = ({data: {result}}) => {
  console.log('Result:', result);
};

  1. 使用性能分析工具:

性能分析工具可以帮助您识别代码中的性能瓶颈,以便进行优化。一些常用的性能分析工具包括:

  • Chrome DevTools:提供了一系列用于分析性能的工具,如Performance、Network、Memory等。
  • Firefox Developer Tools:与Chrome DevTools类似,提供了类似的性能分析功能。
  • Lighthouse:一个开源的自动化工具,用于评估网页的质量和性能,生成报告并提供改进建议。

6.压缩和优化代码:

使用工具(如UglifyJS、Terser等)压缩JavaScript代码,以减小文件大小并提高加载速度。同时,确保删除未使用的代码和注释。

示例

uglifyjs script.js -o script.min.js

  1. 压缩和优化图片:

使用图像压缩工具(如ImageOptim、TinyPNG等)对图片进行压缩,以减小文件大小并提高加载速度。同时,确保使用适当的图片格式(如WebP、JPEG、PNG等)

示例

imageoptim script.jpg

8.使用CDN(内容分发网络):

使用CDN可以将静态资源(如图片、JavaScript和CSS文件)分发到全球各地的服务器。这可以加快资源加载速度,提高性能

示例 在HTML文件中使用CDN提供的JavaScript文件:

<script src="***/ajax/libs/jquery/3.6.0/jquery.min.js"></script>

9.优化网络请求:

尽量减少HTTP请求次数,可以通过合并文件、使用雪碧图(CSS Sprites)、使用图标字体(Icon Fonts)等方式实现。同时,利用浏览器缓存,避免重复请求相同的资源

示例 合并多个CSS为一个文件

<link rel="stylesheet" href="styles.min.css">

10.代码分割(Code Splitting):

将代码分割成多个较小的文件,并在需要时加载。这可以加快初始页面加载速度,提高性能。一些JavaScript框架(如React、Vue等)和打包工具(如Webpack、Rollup等)支持代码分割。

示例 在Webpack配置文件中使用代码分割:

module.exports = {
  // ...
  optimization: {
    splitChunks: {
      cacheGroups: {
        commons: {
          test: /[\\/]node_modules[\\/]/,
          name: "vendors",
          chunks: "all"
        }
      }
    }
  }
  // ...
};

11.延迟加载(Lazy Loading):

对于非关键资源(如图片、脚本等),可以延迟加载,直到用户需要时才加载。这可以加快初始页面加载速度,提高性能。

示例 使用JavaScript延迟加载图片

function lazyLoad(element, offset) {
  offset = offset || 200;

  function checkScroll() {
    const windowBottom = window.innerHeight + window.pageYOffset;
    const elementTop = element.getBoundingClientRect().top;
    const elementBottom = element.getBoundingClientRect().bottom;

    if (windowBottom >= elementTop - offset && windowBottom <= elementBottom + offset) {
      element.src = element.dataset.src;
      checkScroll(); // remove event listener
    }
  }

  window.addEventListener('scroll', checkScroll);
}

const imgElement = document.getElementById('lazy-image');
lazyLoad(imgElement, 200);

总结

窃以为,性能优化是一个持续的过程,而不是一个在开发到一定阶段才去进行的开发流程,一个好的项目,一定是在整个软件开发周期中持续的进行优化和改进的。同样的我们也要结合项目实际情况以及需求进行合理优化,切不能为了性能而牺牲代码的可读性和稳定性。