vue3.0 beta 编译优化研究
在尤雨溪 - 聊聊 Vue.js 3.0 Beta 官方直播完整版 2020-04-21里我发现了一个有意思的工具,输入模板展示它编译优化的结果,网址在这里:https://vue-next-template-explorer.netlify.app/
留意图片中,注意动态的 /* Text */
的注释。识别 _openblock 后,vue 直接会找到带动态属性的节点(是AST里面会有标识声明),并且它标明了 /* Text */
所以 diff 时会直接比对它的文本属性,节省了很大一笔 diff 遍历的次数。
<div>
<span>hello</span>
<span>hello</span>
<span :id="test" :class="clazz">{{msg}}</span>
<span>hello</span>
<span>hello</span>
<span>hello</span>
<span>hello</span>
</div>
import { createVNode as _createVNode, toDisplayString as _toDisplayString, openBlock as _openBlock, createBlock as _createBlock } from "vue"
export function render(_ctx, _cache) {
return (_openBlock(), _createBlock("div", null, [
_createVNode("span", null, "hello"),
_createVNode("span", null, "hello"),
_createVNode("span", {
id: _ctx.test,
class: _ctx.clazz
}, _toDisplayString(_ctx.msg), 11 /* TEXT, CLASS, PROPS */, ["id"]),
_createVNode("span", null, "hello"),
_createVNode("span", null, "hello"),
_createVNode("span", null, "hello"),
_createVNode("span", null, "hello")
]))
}
// Check the console for the AST
能识别出第三个 span 是动态的,并且还会标识它的哪些属性是动态的,其中 {{msg}} 是 TEXT,:class 是 CLASS,:id 是 PROPS
JSX 比起模板它的表达更加灵活,但因为它过于灵活,就无法做到下面的优化:
import { createVNode as _createVNode, toDisplayString as _toDisplayString, openBlock as _openBlock, createBlock as _createBlock } from "vue"
const _hoisted_1 = _createVNode("span", null, "hello", -1 /* HOISTED */)
const _hoisted_2 = _createVNode("span", null, "hello", -1 /* HOISTED */)
const _hoisted_3 = _createVNode("span", null, "hello", -1 /* HOISTED */)
const _hoisted_4 = _createVNode("span", null, "hello", -1 /* HOISTED */)
const _hoisted_5 = _createVNode("span", null, "hello", -1 /* HOISTED */)
const _hoisted_6 = _createVNode("span", null, "hello", -1 /* HOISTED */)
export function render(_ctx, _cache) {
return (_openBlock(), _createBlock("div", null, [
_hoisted_1,
_hoisted_2,
_createVNode("span", {
id: _ctx.test,
class: _ctx.clazz
}, _toDisplayString(_ctx.msg), 11 /* TEXT, CLASS, PROPS */, ["id"]),
_hoisted_3,
_hoisted_4,
_hoisted_5,
_hoisted_6
]))
}
// Check the console for the AST
直接把静态节点抽离出去了,他只会编译阶段创建一遍,之后直接复用对象,不需要再创建了。还有一些其他的优化,比如说可以 cache 绑定的 click 函数,SSR 渲染直接变字符串输出。