幾天前開始我們從設定 → 測試 → 分析,昨天更揭開了 Vapor Mode 與 Alien Signals 的底層優化,今天要做的,就是親眼見證「無 Virtual DOM」的威力:
一開始我們一起學習建立第一個 Vue 專案,事實後派上真正的用場啦!
不過,因為 Vue 3.6 還沒有正式拍板定案,所以要見證奇蹟的時刻,需要使用最新 Vue 3.6 RC / 3.7+,相關指令如下:
npm create vite@latest vue-vapor-demo --template vue
cd vue-vapor-demo
npm install vue@next # 或安裝最新 3.6+ 版本
提示:確保 Vite 版本至少在
5.x
以上,以支援最新的編譯選項。
在 vite.config.ts
中設定 Vue 插件:
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
export default defineConfig({
plugins: [
vue({
vapor: true // 開啟 Vapor Mode
})
]
})
接下來在 main.ts
中照常掛載:
import { createApp } from 'vue'
import App from './App.vue'
createApp(App).mount('#app')
只要在 編譯階段 啟用,Vue 會自動輸出最小化 DOM Patch 指令,不再生成 Virtual DOM。
環境建立後,開始親眼見證歷史性的一刻 magic~
現在我們要模擬「多個 composable 同時更新」的場景,1,000 個計數器同時自動累加:(✪ω✪)
App.vue
<script setup lang="ts">
import Counter from './components/CounterView.vue'
</script>
<template>
<div class="grid">
<Counter v-for="n in 1000" :key="n" />
</div>
</template>
<style>
.grid {
display: grid;
grid-template-columns: repeat(auto-fill, 60px);
gap: 4px;
}
</style>
CounterView.vue
<script setup lang="ts">
import { ref, onMounted, onScopeDispose } from 'vue'
const count = ref(0)
let timer: number
onMounted(() => {
timer = window.setInterval(() => {
count.value++
}, 16) // 每 16ms 更新
})
onScopeDispose(() => clearInterval(timer))
</script>
<template>
<div class="counter">{{ count }}</div>
</template>
<style>
.counter {
width: 60px;
text-align: center;
background: #eee;
padding: 4px;
}
</style>
這裡每個 <CounterView>
都是一個獨立的 composable scope,每 16ms 更新一次。
在程式內做計數:
import { watchEffect } from 'vue'
let updates = 0
watchEffect(() => {
updates++
})
setInterval(() => {
console.log('每秒更新次數:', updates)
updates = 0
}, 1000)
啟用 Vapor Mode 後,預期可以看到更低的 JS 執行時間與更少的無效更新。
Vapor Mode 在多個 composable 高頻更新下明顯更平滑。
模式 | FPS (平均) | Scripting Time | Memory |
---|---|---|---|
Vapor Mode | 55~60 | 低 (直接 patch) | 較低 |
傳統 Virtual DOM | 30~45 | 高 (頻繁 diff) | 偏高 |
透過這個實驗,我們可以感受到:
vite.config.ts
開啟 vapor: true
即可受益但是實戰中不可能只有這樣,甲方的需求永遠都不會滿足,Vapor Mode 的極限能滿足甲方嗎?
來都來了,不然明天試試看!(⁰▿⁰)