高中生打破React性能极限,将React性能提升70%!(上)

简介: 高中生打破React性能极限,将React性能提升70%!

React 是当今最受欢迎的 JavaScript 框架之一,它的创新就是引入了虚拟 DOM 技术,但很多现代框架已经不再采用这种方案。Svelte 的创建者 Rich Harris 曾将其称作纯粹的开销。1.webp.jpg一位名为 Aidenybai 的高中生开发了一个名为 million.js 的轻量级(小于 4KB)虚拟 DOM 库,其可将 React 组件的性能提高多达 70%。2.webp.jpg那 million 是什么,又是如何让 React 的速度提高 70% 的呢?下面就来详细看看!

全文概览:

  • Million.js 基本概念
  • Million.js 使用步骤
  • Million.js 打包体积
  • Million.js 工作原理
  • Million.js 使用场景
  • 总结

Million.js基本概念

Million.js 提供了一个极致优化的虚拟 DOM,可以与 React 兼容。使用 Million 创建 Web 应用程序就像使用 React 组件一样简单(它只是一个包装 React 组件的高阶组件),但加载和渲染速度更快。Million.js 使用经过微调和优化的虚拟 DOM 减少了 React 的开销,就像 React 组件以纯 JavaScript 的速度运行一样。

一个高中生就这么超越了Meta 的整个顶级工程师团队?带着怀疑看了看性能基准对比:

3.webp.jpg数据不言自明,在第二张表中,内存消耗的差异更加显著,它清楚的显示了 Million 如何在内方面得到更好的优化。

那为什么 million.js 会如此之快呢?

React 默认的虚拟 DOM 是实际 DOM 的一种内存抽象。组件被存储在一个树形结构中,当状态发生变化时,React 会创建一个新的虚拟 DOM。接下来,将新的虚拟 DOM 树与旧的虚拟 DOM 树进行比较,找出两者之间的差异。最后,使用这些差异更新实际 DOM 树。这就是所谓的协调过程。但是,创建全新的虚拟 DOM 代价很大。

Million 通过使用块虚拟 DOM,采用了更加精简的方式。将应用程序中的动态部分提取出来并进行跟踪,当状态发生变化时,只对变化的部分进行 diff 操作。相比默认的虚拟 DOM,不需要对整个树进行 diff。由于 Million 跟踪了动态部分的位置,因此可以精确地找到并更新它们,这种方法与 Svelte 很相似。


Million.js使用步骤

在 使用 million 之前,首先需要创建一个 React 项目在,这里略过创建项目的过程。

或者也可以直接克隆官方提供的 React + Vite 项目模板(github.com/aidenybai/m…),打开项目根目录,依次执行 npm installnpm run dev 命令来启动项目,启动完成之后在浏览器输入 localhost:3000 就可以看到以下界面:

4.webp.jpg可以通过以下命令来安装 million 库:

javascript

复制代码

npm install million

使用方式很简单,在组件中引入 million,并在组件中使用:

import React, { useState } from 'react';
import { block } from 'million/react';
import './App.css';
function App() {
  const [count, setCount] = useState(0);
  return (
    <div className="App">
      <h1>Million + React</h1>
      <button onClick={() => setCount((count) => count + 1)}>
        count: {count}
      </button>
    </div>
  );
}
const AppBlock = block(App)
export default AppBlock

可以看到,组件从 million 中引入了 block(),并使用 block() 包裹 App 组件。Million.js 可以让我们创建块(block),块是一种特殊的高阶组件,可以像 React 组件一样使用,但具有更快的渲染速度。

块的一个用例是高效地渲染数据列表。下面在 React 中构建一个数据网格。可以在组件中分别定义 (用于展示数据列表) 和 (用于输入展示列表的行数) 组件,使用 useState() hook 存储要显示的行数。

import React, { useState } from 'react';
import './App.css';
function App() {
  const [rows, setRows] = useState(1);
  return (
    <div>
      <Input value={rows} setValue={setRows} />
      <Table>
        // ...
      </Table>
    </div>
  );
}
export default App;


假设我们通过一个名为 buildData(rows) 的函数获取任意数据数组:

javascript

复制代码

const data = buildData(100);
// [{ adjective: '...', color: '...', noun: '...' }, ... x100]

现在可以使用 Array.map() 在表格中渲染数据:

import React, { useState } from 'react';
import './App.css';
function App() {
  const [rows, setRows] = useState(1);
  const data = buildData(rows);
  return (
    <div>
      <Input value={rows} setValue={setRows} />
      <Table>
        {data.map(({ adjective, color, noun }) => (
          <tr>
            <td>{adjective}</td>
            <td>{color}</td>
            <td>{noun}</td>
          </tr>
        ))}
      </Table>
    </div>
  );
}
export default App;

页面效果如下:8.webp.jpg

它的性能表现非常好。从 0 到 100,几乎没有延迟,但一旦超过 500 左右,渲染时就会有明显的延迟。

这时引入 million 来看看:

import React, { useState } from 'react';
import { block } from 'million/react';
import './App.css';
function App() {
  const [rows, setRows] = useState(1);
  const data = buildData(rows);
  return (
    <div>
      <Input value={rows} setValue={setRows} />
      <Table>
        {data.map(({ adjective, color, noun }) => (
          <tr>
            <td>{adjective}</td>
            <td>{color}</td>
            <td>{noun}</td>
          </tr>
        ))}
      </Table>
    </div>
  );
}
const AppBlock = block(App)
export default AppBlock

此时,再添加超过 500 条数据时,页面渲染就会快很多。

除此之外,Million 还提供了其他实用工具,特别是用于高效地渲染列表。Million 并不推荐将传统的列表包装在block HOC 中进行渲染,而是推荐使用内置的 For 组件:

<For each={data}>
  ({ adjective, color, noun }) => (
    <tr>
      <td>{adjective}</td>
      <td>{color}</td>
      <td>{noun}</td>
    </tr>
  )
</For>

Million.js打包体积

页面的执行性能非常重要,其初始加载也非常重要,其中一个重要因素就是项目的打包体积。这里我们使用 Million 和不使用它构建了相同的应用。

使用纯 React 的打包体积:

7.webp.jpg

使用 Million 的打包体积:6.webp.jpg

可以看到,gzip 捆绑包大小的差异小于 5 kB,这意味着对于多数 React 应用来说,Million 对项目的体积影响可以忽略不计。


Million.js工作原理


最后,我们来看看 million 的工作原理。

React 的虚拟 DOM

虚拟 DOM 的产生是为了解决频繁操作真实 DOM 带来的性能问题。它是真实 DOM 的轻量级、内存中的表示形式。当一个组件被渲染时,虚拟 DOM 会计算新状态和旧状态之间的差异(称为 diff 过程),并对真实 DOM 进行最小化的变化,使它与更新后的虚拟 DOM 同步(这个过程称为协调)。 下面来看一个例子,假设有一个 React 组件


function Numbers() {
  return (
    <foo>
      <bar>
        <baz />
      </bar>
      <boo />
    </foo>
  );
}

当 React 渲染此组件时,它将经过检查更改的 diff 和更新 DOM 的协调过程。这个过程看起来像这样:

  1. 我们得到了两个虚拟 DOM:current(当前的),代表当前 UI 的样子,和 new(新的),代表想要看到的样子。

8.webp (1).jpg

  1. 比较第一个节点,发现没有差异,继续比较下一个9.webp.jpg
  2. 比较第二个节点,发现有一个差异,在 DOM 中进行更新。10.webp.jpg比较第三个节点,发现它在新的虚拟 DOM 中已经不存在了,在 DOM 中将其删除。

14.webp.jpg

  1. 比较第四个节点,发现它在新的虚拟 DOM 中已经不存在了,在 DOM 中将其删除。

15.webp.jpg

  1. 比较第五个节点,发现有差异,在 DOM 中进行更新并完成了整个过程。

16.webp.jpg

diff 过程取决于树的大小,最终导致虚拟 DOM 的性能瓶颈。组件的节点越多,diff 所需要的时间就越长。

随着像 Svelte 这样的新框架的出现,由于性能开销的问题,甚至不再使用虚拟 DOM。相反,Svelte 使用一种称为 "脏检查" 的技术来确定哪些内容已经发生了改变。类似 SolidJS 这样的精细响应式框架更进一步,精确定位于 DOM 中哪些部分发生了变化,并仅更新这部分内容。



高中生打破React性能极限,将React性能提升70%!(下)https://developer.aliyun.com/article/1411539

相关文章
|
7月前
|
存储 缓存 监控
如何避免React性能问题
【4月更文挑战第9天】 提升React应用性能的关键策略包括:最小化渲染,如使用`React.memo`和`PureComponent`;优化列表渲染,如使用虚拟化和`key`属性;代码分割以按需加载;避免内联函数和对象;优化state和props;使用Profiler分析性能;减少网络请求;谨慎使用第三方库;考虑服务端渲染或静态网站生成;并保持应用更新。持续监控和调整是性能优化的重要部分。
61 8
|
7月前
|
前端开发 JavaScript UED
使用React Hooks优化前端应用性能
本文将深入探讨如何使用React Hooks来优化前端应用的性能,重点介绍Hooks在状态管理、副作用处理和组件逻辑复用方面的应用。通过本文的指导,读者将了解到如何利用React Hooks提升前端应用的响应速度和用户体验。
|
7月前
|
JavaScript 前端开发 API
详解React与Vue的性能对比
详解React与Vue的性能对比
332 0
|
1月前
|
JavaScript 前端开发 算法
在性能上,React和Vue有什么区别
【10月更文挑战第23天】在性能上,React和Vue有什么区别
18 1
|
2月前
|
JSON 前端开发 JavaScript
【简单粗暴】如何使用 React 优化 AG 网格性能
【简单粗暴】如何使用 React 优化 AG 网格性能
31 3
|
2月前
|
缓存 前端开发 JavaScript
10 种方案提升你 React 应用的性能
本文首发于微信公众号「前端徐徐」,作者徐徐分享了提升 React 应用性能的方法。文章详细介绍了 `useMemo`、虚拟化长列表、`React.PureComponent`、缓存函数、使用 Reselect、Web Worker、懒加载、`React.memo`、`useCallback` 和 `shouldComponentUpdate` 等技术,通过实际案例和代码示例展示了如何优化 React 应用的性能。这些方法不仅减少了不必要的重新渲染和计算,还提升了应用的响应速度和用户体验。
23 0
|
7月前
|
监控 前端开发 API
如何优化React性能?
【4月更文挑战第9天】提升React应用性能的关键策略包括:使用React.memo和PureComponent防止不必要的重渲染;实施代码分割减少初始加载时间;借助React Profiler定位性能问题;优化state和props以减小大小和复杂性;设置列表项的key属性;避免内联函数和对象;自定义shouldComponentUpdate或React.memo比较函数;使用虚拟化技术渲染大量列表;通过Context API共享数据;以及利用服务端渲染加速首屏加载。不断监控和调整是优化的核心。
61 9
|
4月前
|
前端开发 UED 开发者
React组件优化全攻略:深度解析让你的前端应用飞速运行的秘诀——从PureComponent到React.memo的彻底性能比较
【8月更文挑战第31天】在构建现代Web应用时,性能是提升用户体验的关键因素。React作为主流前端库,其组件优化尤为重要。本文深入探讨了React组件优化策略,包括使用`PureComponent`、`React.memo`及避免不必要的渲染等方法,帮助开发者显著提升应用性能。通过实践案例对比优化前后效果,不仅提高了页面渲染速度,还增强了用户体验。优化React组件是每个开发者必须关注的重点。
73 0
|
7月前
|
前端开发 开发者
React useMemo钩子指南:优化计算性能
React useMemo钩子指南:优化计算性能
|
7月前
|
前端开发
掌握React中的useCallback:优化性能的秘诀
掌握React中的useCallback:优化性能的秘诀