成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

高中生打破React性能極限,將React性能提升70%!

開發 架構
對于很多應用來說,傳統的虛擬 DOM 可能就足夠了,不需要切換到塊虛擬 DOM 或其他以性能為中心的框架。如果應用在大多數設備上運行流暢且沒有性能問題,那么可能不值得花時間和精力過渡到不同的框架。在對技術堆棧進行任何重大更改之前,必須仔細權衡取舍并評估應用的要求。

React 是當今最受歡迎的 JavaScript 框架之一,它的創新之一就是引入了虛擬 DOM,但很多現代框架已經不再采用這種方案,其在某些情況下會影響應用的性能。Svelte 的創建者 Rich Harris 曾將其稱作純粹的開銷。

圖片

一位名為 Aidenybai 的高中生開發了一個名為 million.js 的輕量級(小于 4KB)虛擬 DOM 庫,其可將 React 組件的性能提高多達 70%。

圖片

那 million.js 到底是什么?又是如何讓 React 的速度提高 70% 的呢?下面就來一探究竟!

本文目錄:

  • 基本概念
  • 使用步驟
  • 打包體積
  • 工作原理
  • 使用場景
  • 總結

基本概念

Million.js 提供了一個極致優化的虛擬 DOM,可以與 React 兼容。使用 Million 創建 Web 應用程序就像使用 React 組件一樣簡單(它只是一個包裝 React 組件的高階組件),但加載和渲染速度更快。Million.js 使用經過微調和優化的虛擬 DOM 減少了 React 的開銷,就像 React 組件以純 JavaScript 的速度運行一樣。

一個高中生就這么超越了Meta 的整個頂級工程師團隊?帶著懷疑看了看 JavaScript 框架性能基準測試對比結果:

圖片

數據不言自明,在第二張表中,內存消耗的差異更加顯著,它清楚的顯示了 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 項目模板(https://github.com/aidenybai/million-react),打開項目根目錄,依次執行 npm install 和 npm run dev 命令來啟動項目,啟動完成之后在瀏覽器輸入 localhost:3000 就可以看到以下界面:

圖片

可以通過以下命令來安裝 million 庫:

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 中構建一個數據網格??梢栽诮M件中分別定義 <Table />(用于展示數據列表) 和 <Input />(用于輸入展示列表的行數) 組件,使用 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) 的函數獲取任意數據數組:

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;

頁面效果如下:

它的性能表現非常好。從 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 和不使用它構建了相同的應用。

使用純 React 的打包體積:

使用 Million 的打包體積:

可以看到,gzip 捆綁包大小的差異小于 5 kB,這意味著對于多數 React 應用來說,Million 對項目的體積影響可以忽略不計。

工作原理

最后,我們來看看 million 的工作原理。

React 的虛擬 DOM

虛擬 DOM 的產生是為了解決頻繁操作真實 DOM 帶來的性能問題。它是真實 DOM 的輕量級、內存中的表示形式。當一個組件被渲染時,虛擬 DOM 會計算新狀態和舊狀態之間的差異(稱為 diff 過程),并對真實 DOM 進行最小化的變化,使它與更新后的虛擬 DOM 同步(這個過程稱為協調)。下面來看一個例子,假設有一個 React 組件 <Numbers />:

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

當 React 渲染此組件時,它將經過檢查更改的 diff 和更新 DOM 的協調過程。這個過程看起來像這樣:

  1. 我們得到了兩個虛擬 DOM:current(當前的),代表當前 UI 的樣子,和 new(新的),代表想要看到的樣子。
  2. 比較第一個節點,發現沒有差異,繼續比較下一個。
  3. 比較第二個節點,發現有一個差異,在 DOM 中進行更新。
  4. 比較第三個節點,發現它在新的虛擬 DOM 中已經不存在了,在 DOM 中將其刪除。
  5. 比較第四個節點,發現它在新的虛擬 DOM 中已經不存在了,在 DOM 中將其刪除。
  6. 比較第五個節點,發現有差異,在 DOM 中進行更新并完成了整個過程。

diff 過程取決于樹的大小,最終導致虛擬 DOM 的性能瓶頸。組件的節點越多,diff 所需要的時間就越長。

隨著像 Svelte 這樣的新框架的出現,由于性能開銷的問題,甚至不再使用虛擬 DOM。相反,Svelte 使用一種稱為 "臟檢查" 的技術來確定哪些內容已經發生了改變。類似 SolidJS 這樣的精細響應式框架更進一步,精確定位于 DOM 中哪些部分發生了變化,并僅更新這部分內容。

Million 的虛擬 DOM

2022 年,Blockdom 發布了 ?;诓煌乃悸罚珺lockdom 引入了“塊虛擬DOM”的概念。塊虛擬 DOM 采用不同的 diff 方法,可以分為兩部分:

  • 靜態分析:對虛擬 DOM 進行分析,將樹的動態部分提取到“Edit Map”中,即虛擬DOM的動態部分到狀態的“Edit”(Map)列表中。
  • 臟檢查:對比狀態(而不是虛擬 DOM 樹)以確定發生了什么變化。如果狀態發生了變化,通過 Edit Map 直接更新DOM。

簡而言之,就是對比數據而不是 DOM,因為數據的大小通常比 DOM 的大小小得多。而且對比數據值可能比對比完整的 DOM 節點更簡單。

由于 Million.js 采用了與 Blockdom 類似的方法,因此下面將使用 Million.js 的語法。

下面來看一個簡單的計數器應用以及它如何使用 Million.js 處理:

import { useState } from 'react';
import { block } from 'million/react';
 
function Count() {
  const [count, setCount] = useState(0);
 
  const node1 = count + 1;
  const node2 = count + 2;
 
  return (
    <div>
      <ul>
        <li>{node1}</li>
        <li>{node2}</li>
      </ul>
      <button
        onClick={() => {
          setCount(count + 1);
        }}
      >
        Increment Count
      </button>
    </div>
  );
}
const CountBlock = block(Count);

這個程序很簡單,顯示效果如下:

(1)靜態分析

靜態分析可以在編譯時或運行時的第一步完成,具體取決于是否使用了 Million.js 的實驗性編譯器。

此步驟負責將虛擬 DOM 的動態部分提取到“編輯映射”中。

  1. 這里沒有使用 React 來渲染 JSX,而是使用 Million.js 來渲染它,它將占位符節點(用“?”表示)傳遞到虛擬DOM。這些節點將充當動態內容的占位符,并在靜態分析過程中使用。
  2. 現在開始靜態分析,檢查第一個節點是否有占位符,沒有找到,繼續下一步。
  3. 在第二個節點中檢查占位符,沒有找到,繼續下一步。
  4. 檢查第三個節點的占位符并找到“?”。將占位符添加到“Edit Map”,它將prop1關聯到占位符節點。然后從塊中刪除占位符。
  5. 檢查第四個節點的占位符并找到“?”。將占位符添加到“Edit Map”,它將 prop2 關聯到占位符節點。然后從塊中刪除占位符。
  6. 檢查第五個節點是否有占位符,沒有找到,完成檢測。

(2)臟檢查

創建 Edit Map 后,就可以開始臟檢查了。這一步負責確定狀態發生了什么變化,并相應地更新 DOM。

  1. 可以只區分 prop1 和 prop2,而不是按元素進行區分。由于兩者都與在靜態分析期間創建的“Edit Map”相關聯,因此一旦確定差異,就可以直接更新 DOM。
  2. 比較當前的 prop1 和新的 prop1 值,由于它們不同,因此更新了 DOM。
  3. 比較當前的 prop2 和新的 prop2 值,由于它們不同,因此更新了 DOM。

可以看到,臟檢查比 diff 步驟需要更少的計算。這是因為臟檢查只關心狀態,而不關心虛擬 DOM,因為每個虛擬節點可能需要許多級別的遞歸來確定它是否已經改變,狀態只需要一個淺層相等檢查。

使用場景

Million.js 具有相當高的性能,并且能夠在 JavaScript 框架基準測試中勝過 React。

JavaScript 框架基準測試通過渲染一個包含行和列的大型表格來測試框架的性能。該基準測試旨在測試高度不切實際的性能測試(如添加/替換 1000 行),并不一定代表真實的應用。

那 Million.js 或塊虛擬 DOM 可以用在什么地方呢?

靜態內容多,動態內容少

當有很多靜態內容而動態內容很少時,最好使用塊虛擬 DOM。塊虛擬 DOM最大的優勢就是不需要考慮虛擬 DOM 的靜態部分,所以如果能跳過很多靜態內容,速度會非???。

例如,在這種情況下,塊虛擬 DOM 將比常規虛擬 DOM 快得多:

// ?
<div>
  <div>{dynamic}</div>
  很多靜態內容...
</div>

如果有很多動態內容,可能看不出塊虛擬 DOM 和常規虛擬 DOM 的區別:

// ?
<div>
  <div>{dynamic}</div>
  <div>{dynamic}</div>
  <div>{dynamic}</div>
  <div>{dynamic}</div>
  <div>{dynamic}</div>
</div>

如果構建一個管理系統,或者一個包含大量靜態內容的網站,塊虛擬 DOM 可能非常適合。但是,如果構建一個網站,其中比較數據所需的計算量明顯大于比較虛擬 DOM 所需的計算量,那么可能看不出太大差異。

例如,這個組件不適合塊虛擬 DOM,因為要比較的數據值多于虛擬 DOM 節點:

// 5個要比較的數據值
function Component({ a, b, c, d, e }) {
  // 1個要比較的虛擬DOM節點
  return <div>{a + b + c + d + e}</div>;
}

“穩定”的 UI 樹

塊狀虛擬 DOM 也適用于“穩定”的 UI 樹,或者變化不大的 UI 樹。這是因為 Edit Map 只創建一次,不需要在每次渲染時都重新創建。

例如,以下組件是塊虛擬 DOM 的一個很好的使用場景:

function Component() {
  return <div>{dynamic}</div>;
}

但是這個組件可能比常規的虛擬 DOM 慢:

function Component() {
  return Math.random() > 0.5 ? <div>{dynamic}</div> : <p>sad</p>;
}

注意,“穩定”返回意味著不允許具有非列表類動態的組件(如同一組件中的條件返回)。

細粒度使用

初學者犯的最大錯誤之一是到處使用塊虛擬 DOM。這是個壞主意,因為塊虛擬 DOM 并不總是比常規虛擬 DOM 快。

相反,應該識別塊虛擬 DOM 更快的某些模式,并僅在這些情況下使用它。例如,可能對大表使用塊虛擬 DOM,但對具有少量靜態內容的小表單使用常規虛擬 DOM。

總結

塊虛擬 DOM 為虛擬 DOM 概念提供了一個全新的視角,提供了一種管理更新和最小化開銷的替代方法。盡管它具有潛力,但它并不是一種放之四海而皆準的解決方案,開發人員在決定是否采用這種方法之前應該評估應用的具體需求和性能要求。

對于很多應用來說,傳統的虛擬 DOM 可能就足夠了,不需要切換到塊虛擬 DOM 或其他以性能為中心的框架。如果應用在大多數設備上運行流暢且沒有性能問題,那么可能不值得花時間和精力過渡到不同的框架。在對技術堆棧進行任何重大更改之前,必須仔細權衡取舍并評估應用的要求。

責任編輯:武曉燕 來源: 前端充電寶
相關推薦

2025-01-13 00:00:00

2021-08-27 14:26:06

開發技能React

2019-07-04 15:57:16

數據安全互聯網

2009-05-20 09:02:53

IT職業培訓就業高中生

2019-02-25 07:07:38

技巧React 優化

2024-06-04 00:00:01

微軟EdgeReact

2022-08-03 09:11:31

React性能優化

2019-03-13 10:10:26

React組件前端

2016-12-19 10:00:00

React性能優化

2023-11-01 17:57:56

React應用程序性能

2017-01-04 10:18:00

React NativScrollViewAndroid

2011-04-19 09:40:31

2024-12-20 16:31:34

2019-03-14 15:38:19

ReactJavascript前端

2020-06-22 07:30:00

React開發工具

2023-07-19 15:45:47

ReactDOM輕量級

2009-04-14 15:30:25

2009-08-10 17:08:52

計算機專業就業IT培訓

2017-04-17 06:07:01

React Nativ開發性能

2023-09-20 08:57:09

架構內存
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: www天天操| 国产欧美在线 | 日韩中文字幕在线视频 | 国产欧美日韩精品一区二区三区 | 欧美激情一区二区三区 | 欧美日韩精品免费观看 | 亚洲毛片 | 国产精品日产欧美久久久久 | 午夜电影日韩 | 欧美一级毛片久久99精品蜜桃 | www.久久 | 精品久久久久久亚洲精品 | 色综合久久天天综合网 | 国产日批 | 九九综合九九 | 国产福利一区二区 | 国产激情视频网址 | 国产成人网 | 午夜精品久久久久久久久久久久 | 黄色三级在线播放 | 欧美日韩视频在线第一区 | 免费看国产a | 欧美成人一级 | 精彩视频一区二区三区 | a在线视频观看 | 免费成年网站 | 国产中文字幕在线观看 | 欧美a√| 免费在线观看黄色av | 欧美久久国产精品 | 欧美激情视频一区二区三区免费 | 中文字幕一区在线 | 午夜激情小视频 | 国产激情一区二区三区 | 午夜精品福利视频 | 国产精品亚洲精品久久 | 国内自拍视频在线观看 | 久久成人精品 | 精品国产视频 | 欧美成人免费在线 | 欧美在线|