oboard

oboard

https://oboard.eu.org/
github
email
tg_channel
medium

Vue Vapor Mode深度解析:開啟無虛擬DOM的高效JavaScript編譯策略

Vapor Mode是 Vue.js沒有虛擬 DOM的一種編譯策略,將代碼編譯成高效的 JavaScript 輸出,使用佔用的內存,減輕運行時的負擔,減小編譯後的體積,從而提高 Vue.js 應用的性能。
可以通過Vue Vapor SFC Playground體驗 Vapor Mode,
通過Vue Volar Template Explorer探究模板的轉換方式。

工作方式

性能對比

如何在自己的 Vite 項目中開啟 Vapor Mode#

Demo 參考 sxzz/vue-vapor-demo

將 vue 和 @vitejs/plugin-vue 的版本升級為 vapor 版
package.json

"dependencies": {
	"vue": "npm:@vue-vapor/vue@latest"
},
"devDependencies": {
    "@vitejs/plugin-vue": "npm:@vue-vapor/vite-plugin-vue@latest",
}

createApp 改為 createVaporApp

import { createVaporApp } from 'vue/vapor'
import './style.css'
import App from './App.vue'

const create = createVaporApp
create(App as any).mount('#app')

檢測 Vapor 是否開啟的方法#

import { ref, getCurrentInstance } from 'vue'

const msg = ref('Hello World!')

// @ts-expect-error
const isVapor = getCurrentInstance().vapor

探索 Vapor Mode 編譯後的 js#

這裡我們編寫一個極為簡單的 vue 文件,來探索 Vapor Mode 的編譯產物

<script setup lang="ts">
import { ref } from 'vue'
const msg = ref('Hello World!')
const classes = ref('p')
</script>

<template>
<h1 :class="classes">{{ msg }}</h1>
</template>

VAPOR ON

/* Analyzed bindings: {
"ref": "setup-const",
"msg": "setup-ref"
} */
import { defineComponent as _defineComponent } from 'vue/vapor'
import { renderEffect as _renderEffect, setText as _setText, setClass as _setClass, template as _template } from 'vue/vapor';
const t0 = _template("<h1></h1>")
import { ref } from 'vue'

const __sfc__ = _defineComponent({
	vapor: true,
	__name: 'App',
	setup(__props) {
	
	const msg = ref('Hello World!')
	
	return (() => {
		const n0 = t0()
		_renderEffect(() => _setText(n0, msg.value))
		_renderEffect(() => _setClass(n0, classes.value))
		return n0
	})()
	}
})
__sfc__.__file = "src/App.vue"
export default __sfc__

VAPOR OFF

/* Analyzed bindings: {
"ref": "setup-const",
"msg": "setup-ref"
} */
import { defineComponent as _defineComponent } from 'vue'
import { toDisplayString as _toDisplayString, normalizeClass as _normalizeClass, openBlock as _openBlock, createElementBlock as _createElementBlock } from "vue"

import { ref } from 'vue'

const __sfc__ = _defineComponent({
	__name: 'App',
	setup(__props) {
		const msg = ref('Hello World!')
		const classes = ref('p')
		return (_ctx,_cache) => {
			return (_openBlock(), _createElementBlock("h1", {
				class: _normalizeClass(classes.value)
			}, _toDisplayString(msg.value), 3 /* TEXT, CLASS */))
		}
	}
})
__sfc__.__file = "src/App.vue"
export default __sfc__

Vapor Mode 開啟時的編譯產物特點:#

  1. 模板編譯:使用_template函數來定義模板,這個函數是 Vue 內部用於生成模板的函數。
  2. 渲染效果:使用_renderEffect來處理響應式數據的渲染,這是一個優化版的渲染函數,用於在 Vapor Mode 下更高效地更新 DOM。
  3. 文本設置:使用_setText函數來設置元素的文本內容,這表明 Vapor Mode 使用了一種更直接的方式來更新文本節點。

Vapor Mode 關閉時的編譯產物特點:#

  1. 模板編譯:使用傳統的createElementBlock來創建元素,這是 Vue 標準編譯流程中用於生成虛擬 DOM 節點的函數。
  2. 文本轉換:使用_toDisplayString來將數據轉換為可顯示的字符串,這是 Vue 在處理數據綁定時的標準做法。
  3. 塊級渲染:使用_openBlock來處理塊級渲染,這是 Vue 在處理多個同級節點時的標準做法。

編譯產物的對比:#

  • 性能優化:Vapor Mode 的編譯產物進行了更多的優化,以減少運行時的 DOM 操作和提高渲染效率。
  • API 使用:Vapor Mode 下使用的 API(如_renderEffect_setText)與標準模式下的 API 有所不同,為了實現更高效的渲染邏輯。

Vapor Mode API#

  1. renderEffect:此函數負責監聽類、屬性和文本的更改,以確保在更新時對這些節點進行正確的更改。
  2. setClass:顧名思義,此函數將類分配給節點元素。它接受兩個參數:一個 element(或 node)和它分配給元素的 class。
  3. setDynamicProp:此函數用於設置元素上的動態屬性。它需要三個參數:element、key 和 value。這些用於確定每次調用此函數時分配或更新的適當值。
  4. setText:此函數接受一個 node 和可能的值。它將給定的值設置為節點的 textContent,同時還驗證內容是否已被修改。
  5. template:此函數接受一個有效的 HTML 字符串並從中創建一個元素。檢查該函數時,我們可以看到它使用基本的 DOM 操作方法。具體來說,使用 document.createElement 創建元素。然後使用 innerHTML 追加元素的內容,innerHTML 接受 HTML 字符串。

總結#

2024 年,Vue 的 Vapor Mode 革新了前端開發領域,以其卓越的性能提升,為 Vue 生態系統帶來了前所未有的變革。我們滿懷期待地展望 Vapor Mode 在未來的表現,相信它將為開發者帶來更加流暢和高效的開發體驗。

載入中......
此文章數據所有權由區塊鏈加密技術和智能合約保障僅歸創作者所有。