先建立 Vue 3.5 Baseline,再談 Vue 3.6 是否真的改善
昨天建立了 VDOM Stress Test,同一個 Scenario,分別測試:
100
500
1000
5000 Nodes
今天目的是想 先知道大量 UI Rendering 的成本分布,再拿 Vue 3.5.40 結果與 Vue 3.6.0-rc.2 比較。
如果只記錄一個 Render Duration,我們只能知道這次比較慢;如果要驗證 Vue 版本的效能變化,還需要知道成本大致落在哪個區域:
JavaScript?
Browser Style?
Layout?
Painting?
這也是明天進入 Vue 3.6 Validation 前,需要先建立的 Cost Map。
一次大量 UI Rendering,可以先用下面這個模型理解:
Application
│
▼
JavaScript / Vue
│
├─ Render
├─ VNode Creation
├─ Diff / Patch
└─ DOM Mutation
│
▼
Browser Pipeline
│
┌─────┼─────┐
▼ ▼ ▼
Style Layout Paint
因此這次 Baseline 主要觀察四個面向:
| 觀察面向 | Chrome / Scenario 指標 |
|---|---|
| JavaScript | Scripting |
| Style | Recalculate Style |
| Layout | Layout |
| Painting | Paint |
| Scenario | Render Duration |
這裡要先把量測邊界講清楚:Scripting 不等於 Vue Runtime,它可能包含 Application JavaScript、Vue Runtime,以及其他 JavaScript 工作。
同樣地,Layout / Paint 也不能直接視為 Vue Cost。
而 Render Duration 是 Scenario 自己量到的操作時間,也不能直接拿來和 Chrome Trace 裡各 category 的數字相加。
所以今天建立的,是 Cost Map,我們先觀察 Node 數量增加後,哪些成本項目開始明顯成長?
先看第一次建立 UI 的結果。
| Nodes | 100 | 500 | 1000 | 5000 |
|---|---|---|---|---|
| Render Duration | 4.3 ms | 11.8 ms | 18.3 ms | 63.2 ms |
| Scripting | 9 ms | 16 ms | 25 ms | 91 ms |
| Recalculate Style | 0.6 ms | 2.5 ms | 4.9 ms | 16.9 ms |
| Layout | 4.8 ms | 22.4 ms | 44.8 ms | 218.8 ms |
| Paint | 2.3 ms | 5.0 ms | 6.7 ms | 5.8 ms |
Node 數量從 100 增加到 5000 時,Render Duration 從 4.3 ms 增加到 63.2 ms,但更值得注意的是各分類的成長幅度。

其中 Layout 從 4.8 ms 增加到 218.8 ms,成長約 45.6 倍,接近 Node 數量的 50 倍成長,這代表在這個 Scenario 中,Mount 階段的主要成本來源逐漸往 Browser Layout 集中。
但這裡有一個很重要的量測細節:
這些數字不是同一個時間分母下可以直接相加的成本。
例如 N=5000 時:
Scenario Render Duration = 63.2 ms
Chrome Layout = 218.8 ms
Layout 數字大於 Render Duration,並不代表測量錯誤,因為兩者的定義不同:
Render Duration
↓
Scenario 自己量測的操作時間
Chrome Trace
↓
特定事件 / category 的 trace measurement
因此這裡我們只拿它們觀察成長趨勢,不把它們當成可以互相加總的時間。
這個 Scenario 的 Card List 使用 CSS Grid:
.cards__list {
display: grid;
grid-template-columns: repeat(
auto-fill,
minmax(160px, 1fr)
);
}
當 5,000 個 Card 第一次進入 DOM,Browser 需要處理大量元素的幾何資訊:
5000 Cards
│
▼
Grid calculation
│
▼
Card size / position
│
▼
Layout geometry
因此目前可以確認 大量 UI 第一次 Mount 時,Browser Layout 會隨 Node 數量快速增加。
這也是為什麼只看 Vue / VDOM 還不夠,因為 Vue 完成 Render、VNode 建立與 DOM 操作之後,Browser 還需要處理實際的頁面 Layout。
接著測試已經存在的 UI,也就是:
Mount
↓
已有 100 / 500 / 1000 / 5000 Nodes
↓
Trigger Update
結果如下:
| Nodes | 100 | 500 | 1000 | 5000 |
|---|---|---|---|---|
| Render Duration | 1.5 ms | 4.9 ms | 8.6 ms | 24.9 ms |
| Scripting | 4 ms | 8 ms | 13 ms | 43 ms |
| Recalculate Style | 0.1 ms | 0.4 ms | 0.1 ms | 0.1 ms |
| Layout | 0.2 ms | 0.4 ms | 0.4 ms | 1.0 ms |
| Paint | 0.4 ms | 1.1 ms | 1.1 ms | 1.6 ms |
這次最明顯的現象,是 Mount 與 Update 的 Layout 數字差距非常大。
Node 數量仍然是 5,000,但 Layout 從 Mount 的 218.8 ms 降到 Update 的 1.0 ms,也就是約 219 倍的差距,如下圖所示:

換句話說,Node 數量本身不能直接推導每次 Update 都會產生同等規模的 Layout Cost。
這個 Scenario 的 Update 會重新建立一個 Card[]:
const next: Card[] = []
for (let i = 1; i <= selectedCount.value; i++) {
next.push({
id: i,
title: `Card #${i}`,
})
}
cards.value = next
雖然資料陣列重新建立,但新舊資料維持:
相同 key
相同順序
相同數量
相同 DOM 結構
例如:
Old VNode New VNode
key = 1 ───────→ key = 1
key = 2 ───────→ key = 2
key = 3 ───────→ key = 3
... ...
key = 5000 ───────→ key = 5000
因此這次 Update 並不是重新建立 5,000 個不同結構的 UI,它更接近:
New Array
│
▼
Reactive Trigger
│
▼
Component Render
│
▼
VNode Creation
│
▼
Reconciliation / Patch
│
▼
必要時更新 DOM
在這個 Scenario 裡,DOM 結構維持穩定,因此 Update 階段沒有出現 Mount 時同等規模的 Layout 成長,代表 不同階段,成本結構可能完全不同。

把今天的觀察整理起來:
VDOM Stress Test
│
┌──────────┴──────────┐
▼ ▼
Mount Update
│ │
▼ ▼
Layout 成長明顯 Layout 維持較低
│ │
▼ ▼
Browser Pipeline JS / Render /
值得觀察 Patch 值得觀察
但這張圖只代表這次 Vue 3.5.40 初始觀察到的成本分布,但是還不能回答 Vue 3.6 是否改善了其中任何一層?
因為目前的 Scripting 仍然包含多種 JavaScript 工作,Layout / Paint 也屬於 Browser rendering cost。
這次 Day 18 的數字,是透過 Chrome DevTools Performance 人工單次錄製與讀值取得,因此它適合用來:
但它不適合直接拿來當作後續 Vue 3.5 / Vue 3.6 的正式 A/B measurement。
後續正式版本比較會使用校準後的自動化 CDP measurement protocol,包含固定的 measurement window、warm-up、multiple trials 與統一的 extraction / aggregation。
所以今天這組數字的角色很明確:
它是 Initial Baseline Observation,不是最後的版本比較數據。
這個區分很重要,否則很容易把不同 measurement protocol 的數字直接放在一起比較。
今天把問題拆開後,可以看到:
Node ↑
↓
Layout 顯著增加
大量 UI 第一次進入 DOM 時,Browser Layout 是值得關注的成本。
Node = 5000
Mount Layout
218.8 ms
↓
Update Layout
1.0 ms
相同 Node 數量下,Update 並沒有產生同等規模的 Layout 成本。
同時,Scripting 仍然是 Update 階段值得觀察的主要區域,但目前還不能把它直接等同於 Vue Runtime。
VDOM Stress Test
│
├── Mount
│ └── Layout 成長明顯
│
└── Update
├── Scripting 值得觀察
└── Layout 成本明顯較低
明天再用相同 Scenario 進入 Vue 3.6.0-rc.2 Validation,問題就可以進一步縮小成:哪些成本真的發生變化,以及這些變化能不能歸因到 Vue Runtime。