首页>>前端>>Vue->vue3中的编译器原理和优化策略

vue3中的编译器原理和优化策略

时间:2023-11-29 本站 点击:0

学习目标

编译器原理

vue3编译过程剖析

vue3编译优化策略

在初始化之前可能有编译的过程,最终的产物是个渲染函数,我们知道渲染函数返回的值是一个虚拟DOM(vnode),那么这个虚拟DOM在我们后续的更新过程中到底有什么作用呢?我们今天就来探讨一下。

编译器原理

1.概念

广义上的编译原理:编译器是将源代码转化成机器码的软件;所以编译的过程则是将源代码转化成机器码的过程,也就是 cpu 可执行的二进制代码。 例如使用高级语言java编写的程序需要编译成我们看不懂但计算机能看懂的的字节码。

如果了解过编译器的工作流程的同学应该知道,一个完整的编译器的工作流程会是这样:

首先,parse 解析原始代码字符串,生成抽象语法树 AST。

其次,transform 转化抽象语法树,让它变成更贴近目标「DSL」的结构。

最后,codegen 根据转化后的抽象语法树生成目标「DSL」的可执行代码。

2.vue中的编译

在vue里也有编译的过程,我们经常写的那个HTML模版,在真正工作的时候,并不是那个HTML模版,它实际上是一个渲染函数,在这个过程中就发生了转换,也就是编译,也就是那个字符串的模版最终会变成一个JS函数,叫render函数。所以在这个过程中我们就需要引入编译器的概念。在计算机中当一种东西从一种形态到另一种形态进行转换的时候,就需要编译。编译器:用来将模板字符串编译成为 JavaScript 渲染函数的代码

那么vue中的编译发生在什么时候呢?

这个时候我们就需要进一步了解vue包的不同版本的不同功能了。vue有携带编译器和不携带编译的包(对不同构建版本的解释)。

3.运行时编译

在使用携带编译器(compiler)的vue包的时候,vue编译的时刻是发生在挂载($mount)的时候。

4.运行时不编译

如果使用未携带编译器的vue包的时候,vue在运行时是不会进行编译的。那么它的编译又发生在什么时候呢?使用未携带编译器的vue包的时候,需要进行预编译,也就是基于构建工具使用,就是我们平时使用的vue-cli进行构建的项目,就是使用webpack调用vue-loader进行预编译,将所有vue文件,就是SFC,将里面的template模版部分转换成render函数。这样做的好处就是vue的包体积变小了,执行的时候速度更快了,因为不需要进行编译了。

vue编译器原理

简单来说就是:先将template模版转换成ast抽象语法树,ast再转换成渲染函数render。

那么什么是是ast抽象语法树呢?

1.ast抽象语法树

在template模版和render函数之间有一个中间产物叫做ast抽象语法树。它就是个js对象,它能够描述当前模版的结构信息,跟vnode很类似。注意,ast只是程序运行过程中编译产生的,它跟我们最终程序的运行是没有任何关系的。也就是当这个渲染函数生成之后,ast的生命周期就结束了,不再需要了,而那个虚拟DOM则伴随整个程序的生命周期。这个就是ast和虚拟DOM的本质区别。

2.为什么需要ast呢

在ast转换成render函数的过程中,需要进行特别的操作。第一次,将template转成的ast是个非常粗糙的js对象,是一次非常粗糙的转换,类似正则表达式的匹配,然后我们的template模版中还有很多表达式,指令,事件需要重新解析,经过这些具体的深加工的解析(transform)之后会得到一个终极ast,然后这个对这个终极ast进行generate,生成render函数

template=>ast=>transform=>ast=>render

3.mini版vue编译器

下面我们来看一个mini版的vue编译器,具体代码已省略,具体代码我已经放在Github上了:mini-vue-compiler

functiontokenizer(input){...}functionparse(template){consttokens=tokenizer(template)...}functiontransform(ast){...}functiontraverse(ast,context){...}functiongenerate(ast){...}functioncompile(template){//1.解析constast=parse(template)console.log(JSON.stringify(ast,null,2))//2.转换transform(ast)//3.生成constcode=generate(ast)console.log(code)//returnfunctionrender(ctx){//returnh("h3",{},//ctx.title//)}returnnewFunction(code)()}lettmpl=`<h3>{{title}}</h3>`compile(tmpl)

大概有以上操作,其中parse函数就是发生在把template转换成ast的这过程,具体是通过一些正则表达式的匹配template中的字符串。比如将

xxx


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:/Vue/830.html