如何精通JavaScript 能优化

使用代码分割、延迟加载、使用 Web Workers、压缩文件和异步加载等技术提升您的 JavaScript 技能。

译自 How To Master JavaScript Performance Optimization,作者 Alexander T Williams。

JavaScript 是现代 Web 应用程序的基石,为从动态内容到交互式功能的一切提供支持。然而,随着应用程序变得越来越复杂,确保 JavaScript 能够高效运行变得至关重要。

随着用户对更快、更具响应性的应用程序的需求不断增长,开发人员必须优先考虑 JavaScript 优化以满足这些期望。从减少加载时间到提高交互性,优化您的 JavaScript 可以显著提高 Web 应用程序的整体性能。

为什么优化 JavaScript 的性能

正确理解网站的性能是优化 JavaScript 代码的第一步。

考虑到这一点,衡量您的网站或应用程序的性能至关重要,因为它可以帮助您识别影响下载时间、渲染速度和整体用户体验的瓶颈。

如果没有对性能进行适当的衡量,您可能会浪费时间应用优化,而这些优化并不能解决您的网站所面临的实际问题。

分析性能数据

有几种工具可以帮助您有效地衡量性能。内置的浏览器工具,例如 Chrome DevTools,提供关于网络活动、加载时间和 CPU 使用率的全面而有价值的见解

收集完性能数据后,下一步是确定哪些优化是必要的。

这些工具可以让您看到页面中哪些部分加载时间最长,以及哪些脚本可能会减慢网站速度。除此之外,性能 API 还可以提供更复杂的数据,用于深入分析。

收集完性能数据后,下一步是确定哪些优化是必要的。并非每种技术都适合每个项目,因此根据您网站的具体需求进行优先排序非常重要。

例如,如果您的分析表明事件处理程序会导致延迟,您可以专注于改进事件管理。类似地,如果大型 JavaScript 文件会减慢加载时间,缩小和异步加载可能是正确的解决方案。

此外,它还可以帮助您遵守 GDPR,或与您的网站或应用程序相关的欧盟、美国或其他地方的任何数据保护法规。优化您的 JavaScript 有助于提高性能,同时确保您的数据处理实践符合标准。

正确管理的代码可以帮助最大限度地减少不必要数据的收集,从而简化尝试遵守和遵循重要监管要求的过程。

优化 JavaScript 性能的挑战

我们都经历过:如果您的代码没有得到妥善管理,JavaScript 有时会成为一个真正的头痛问题。

您可能遇到的一些常见问题包括质量较差的事件处理,这会导致深层调用堆栈和更慢的性能。无序的代码是另一个大问题,会导致资源分配效率低下,并使浏览器更难快速执行脚本。

代码拆分允许您将 JavaScript 代码分解成更小、更易于管理的块。

然后是过度依赖的问题,这会减慢应用程序的速度,通常会显著减慢速度,尤其是对于带宽有限的移动用户而言——而且不要忘记,低效的迭代会不必要地拖延处理时间。

理解和实现代码拆分

代码拆分允许您将 JavaScript 代码分解成更小、更易于管理的块——这在您的应用程序变得越来越复杂时至关重要,有助于减少加载时间并提高用户的初始渲染速度。

那么,如何进行代码拆分呢?一种常用的方法是使用动态导入,它允许您仅在需要时加载 JavaScript 模块,而不是一次性将整个应用程序加载到用户身上。这就像只为周末旅行打包必需品,而不是打包整个衣橱。

根据最近的调查统计,48.9% 的开发人员已采用动态导入按需加载模块45.7% 的开发人员正在使用服务工作者 来增强离线用户体验。

同样,对于 JS 库也是如此,允许进行各种应用内操作,例如在 React 应用中查看文档,动态在实时分析仪表板中渲染图表,或加载交互式地图以用于基于位置的服务。然后是 webpack,一个工具,一旦你掌握了它,就会感觉有点像魔法;它可以自动将你的代码拆分成更小的块,按需加载它们。

如何实现代码拆分

  1. 动态导入: 使用import() 函数在需要时加载模块。例如:
import('./module.js').then(module => {
  module.doSomething();
});
  1. Webpack 配置: 配置 webpack 使用SplitChunksPluginoptimization.splitChunksoptions 自动将代码拆分成更小的块。

  2. React.lazy: 在 React 应用中,使用React.lazy 进行组件级代码拆分:

const MyComponent = React.lazy(() => import('./MyComponent'));

实现延迟加载以提高性能

延迟加载是一种很棒的技术,可以通过延迟加载非必要资源来提高 Web 应用的性能,直到它们真正需要时才加载。

简而言之,延迟加载允许这些元素仅在进入用户的视野时加载,而不是让用户等待每个图像、视频或媒体文件预先加载。

延迟加载最常见的用例包括图像、视频和其他媒体密集型内容等元素。使用延迟加载可以大幅减少初始加载时间,从而增强网站或应用的整体用户体验。

实现延迟加载的一种流行方法是通过 Intersection Observer API。这个特定的 API 允许你检测元素何时进入或退出视窗,因此你可以在内容即将对用户可见时才加载它。它效率高且设置起来相对容易。

如何实现延迟加载

  1. Intersection Observer API: 检测元素何时进入视窗并动态加载内容:
const observer = new IntersectionObserver((entries) => {
  entries.forEach(entry => {
    if (entry.isIntersecting) {
      loadImage(entry.target);
      observer.unobserve(entry.target);
    }
  });
});

document.querySelectorAll('img[data-src]').forEach(img => observer.observe(img));
  1. 对于 React 开发人员,React.lazy 函数是延迟加载组件的强大工具。使用React.lazy,你可以在组件级别拆分代码,以便仅在需要时加载应用的必要部分。

利用 Web Workers 卸载繁重的计算

Web Workers 是现代 Web 开发中的一项强大功能,旨在帮助处理繁重的计算,而不会减慢用户界面。

Web Workers 从主线程卸载密集型任务,通过在后台线程中运行脚本,提供流畅且响应迅速的用户体验。

Web Workers 通过启用并行执行来显著提高性能;因此,当主线程处理用户交互和渲染时,Web Workers 负责后台的资源密集型操作,例如数据处理和计算。这可以防止 UI 由于长时间运行的脚本而变得无响应。

使用 Web Workers 的一些更实际的示例包括卸载基本数据处理任务。例如,当处理需要排序、过滤或复杂计算的大型数据集时,Web Worker 可以管理这些操作,而不会冻结主 UI 线程。

如何利用 Web Workers

  1. 创建 Web Worker: 为工作者创建一个单独的 JavaScript 文件:
// worker.js
self.onmessage = (e) => {
  const result = computeHeavyTask(e.data);
  postMessage(result);
};
  1. 使用 Web Worker: 从主线程实例化并与工作者通信:
const worker = new Worker('worker.js');

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

worker.postMessage(data);

JavaScript 优化的其他技术

优化 JavaScript 不仅仅是代码分割和延迟加载,还有其他一些技术可以显著提高应用程序的性能。

异步加载允许脚本与其他资源并行获取。

一种重要的方法是 压缩和压缩 JavaScript 文件,这涉及从代码中删除不必要的字符和空格,而不会改变其功能。像 UglifyJS 这样的工具可以帮助完成此过程,使用 gzip 或 Brotli 压缩可以进一步减小文件大小,从而加快加载时间。

另一方面,异步加载允许脚本 与其他资源并行获取,防止它们阻塞页面的渲染。HTML 中的 async 属性通常用于此目的。

使用 defer 属性延迟脚本,确保 代码在初始 HTML 解析后执行,这提高了用户与网站交互的速度。

利用 HTTP/2 和 JavaScript CDN 可以进一步提高网站或应用程序的性能。

HTTP/2 引入了多路复用等功能,允许多个请求同时通过单个连接发送,从而减少延迟。使用 内容交付网络 (CDN) 为您的 JavaScript 文件提供服务 可以保证它们从更靠近用户的位置提供服务,从而加快交付速度。

提升您的 JavaScript 水平

代码分割、延迟加载、使用 Web Workers、压缩文件和利用异步加载等技术并不完全是秘密,但开发人员并没有充分利用它们——远非如此。

每种方法都可以提高应用程序的速度和响应能力,将它们纳入开发工作流程将提供更流畅的用户体验,并使您的应用程序保持领先地位。

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注