vue 编译
vue-loader 的编译过程
输入是一个 vue 单文件,最终输出的结果是可以被直接执行的 js 代码。
细化一下这中间的步骤,vue-loader 将 vue 文件编译到输出 bundle.js 的过程主要是调用了下面的四个小 loader, 它们分别是:
selectorstyle-compilertemplate-compilerbabel-loader
以上四个 loader,除了 babel-loader 是外部的 package,其他三个都存在于 vue-loader 的内部
1. JS 部分
首先分析 script 部分
/* script */
import __vue_script__ from "!!babel-loader!../../lib/selector?type=script&index=0&bustCache!./basic.vue";
从做右到左,也就是 basic.vue 被先后被 selector 和 babel-loader 处理过了。
selector(参数 type=script) 的处理结果是将 basic.vue 中的 javaScript 抽出来之后交给 babel-loader去处理,最后生成可用的 javaScript
2. Template
再来分析 template 部分
/* template */
import __vue_template__ from '!!../../lib/template-compiler/index?{"id":"data-v-793be54c","hasScoped":false,"buble":{"transforms":{}}}!../../lib/selector?type=template&index=0&bustCache!./basic.vue';
同样的,从左到右,basic.vue 先后被 selector 和 template-compiler 处理过了。 selector (参数 type=template) 的处理结果是将 basic.vue 中的 template 抽出来之后交给 template-compiler 处理,最终输出成可用的 HTML。
3. Style 部分
/* styles */
import __vue_styles__ from '!!vue-style-loader!css-loader!../../lib/style-compiler/index?{"vue":true,"id":"data-v-793be54c","scoped":false,"hasInlineConfig":false}!../../lib/selector?type=styles&index=0&bustCache!./basic.vue';
style 涉及的 loader 较多,一个一个来分析, 从上代码可知,basic.vue 先后要被 selector, style-compiler, css-loader 以及 vue-style-loader 处理。 selector (参数 type=style) 的处理结果是将 basic.vue 中的 css 抽出来之后交给 style-compiler 处理成 css, 然后交给 css-loader 处理生成 module, 最后通过 vue-style-loader 将 css 放在 <style> 里面,然后注入到 HTML 里。
vue 模板编译过程
在使用 Vue 开发的过程中,基本都是使用模板的方式。Vue 会通过编译器将模板通过几个阶段最终编译为 render 函数,然后通过执行 render 函数生成 Virtual DOM 最终映射为真实 DOM。
这个过程又分为三个阶段,分别为:
- parse 过程: 将 template 利用正则转化成 AST 抽象语法树。
- optimize 过程: 优化 AST,标记静态节点,后 diff 过程跳过静态节点,提升性能。
- generate 过程: 将 AST 转换为
render函数
在第一个阶段中,最主要的事情还是通过各种各样的正则表达式去匹配模板中的内容,然后将内容提取出来做各种逻辑操作,接下来会生成一个最基本的 AST 对象
{
// 类型
type: 1,
// 标签
tag,
// 属性列表
attrsList: attrs,
// 属性映射
attrsMap: makeAttrsMap(attrs),
// 父节点
parent,
// 子节点
children: []
}
然后会根据这个最基本的 AST 对象中的属性,进一步扩展 AST。
当然在这一阶段中,还会进行其他的一些判断逻辑。比如说对比前后开闭标签是否一致,判断根组件是否只存在一个,判断是否符合 HTML5 规范等等问题。
接下来就是优化 AST 的阶段。在当前版本下,Vue 进行的优化内容其实还是不多的。只是对节点进行了静态内容提取,也就是将永远不会变动的节点提取了出来,实现复用 Virtual DOM,跳过对比算法的功能。在下一个大版本中,Vue 会在优化 AST 的阶段继续发力,实现更多的优化功能,尽可能的在编译阶段压榨更多的性能,比如说提取静态的属性等等优化行为。
最后一个阶段就是通过 AST 生成 render 函数了。其实这一阶段虽然分支有很多,但是最主要的目的就是遍历整个 AST,根据不同的条件生成不同的代码罢了。