vue-loader&vue-template-compiler详解

在 vue 工程中,安装依赖时,需要 vue 和 vue-template-compiler 版本必须保持一致,否则会报错。

Module build failed: Error: Cannot find module ‘vue-template-compiler’

为什么二者版本必须一致呢?vue-template-compiler 承担哪些作用?其和 vue-loader 又有何关联?

vue-loader&vue-template-compiler详解_第1张图片

vue-template-compiler

作用: 该模块可用于将 Vue 2.0 模板预编译为渲染函数(template => ast => render),以避免运行时编译开销和 CSP 限制。大都数场景下,与 vue-loader一起使用,只有在编写具有非常特定需求的构建工具时,才需要单独使用它

内容安全策略 (CSP) 是一个附加的安全层,用于帮助检测和缓解某些类型的攻击,包括跨站脚本 (XSS) 和数据注入等攻击。

需要注意的是,This package is auto-generated. For pull requests please see src/platforms/web/entry-compiler.js.这个包是自动生成的,请查看 entry-compiler.js 文件。

其文件路径,vue/src/platforms/web/entry-compiler.js

export { parseComponent } from 'sfc/parser'
export { compile, compileToFunctions } from './compiler/index'
export { ssrCompile, ssrCompileToFunctions } from './server/compiler'
export { generateCodeFrame } from 'compiler/codeframe'

可得知,vue-template-compiler 的代码是从 vue 源码中抽离的!接着,我们对比一下 vue-template-compiler 和 vue 关于编译的 API。发现对于 compile 等函数是一致,只是 vue-template-compiler 开放的参数和方法更多。因此,vuevue-template-compiler 的版本必须一致(同一份源码)!

const compiler = require('vue-template-compiler')

const result = compiler.compile(`
  

This is my vue render test

my name is {{myName}}

`
) console.log(result)

compiler.compile(template, [options])

{
  ast: ASTElement, // 解析模板生成的ast
  render: string,	 // 渲染函数
  staticRenderFns: Array<string>, // 静态子树
  errors: Array<string>,
  tips: Array<string>
}
{
  ast: {
    type: 1,
    tag: 'div',
    attrsList: [ [Object] ],
    attrsMap: { id: 'test' },
    rawAttrsMap: {},
    parent: undefined,
    children: [ [Object], [Object], [Object] ],
    plain: false,
    attrs: [ [Object] ],
    static: false,
    staticRoot: false
  },
  render: `with(this){return _c('div',{attrs:{"id":"test"}},[
		_m(0),			// 上述提到的静态子树,索引为0 

This is my vue render test

_v(" "), // 空白节点

之间的换行内容 _c('p',[_v("my name is "+_s(myName))]) //

my name is {{myName}}

])}`, staticRenderFns: [ `with(this){return _c('div',[_c('p',[_v("This is my vue render test")])])}` ], errors: [], tips: [] }

需要注意的是:children 存在3个节点,其中第二个为空节点 { type: 3, text: ' ', static: true } 即代码中的

之间的内容。

compiler.compileToFunctions(template)

简化版的 compiler.compile() ,但只返回

{
  render: Function,
  staticRenderFns: Array<Function>
}

其通过 new Function() 方式

compiler.parseComponent(file, [options])

将 SFC (单文件组件或* .vue文件)解析为描述符「以下述提供SFC为例」

{
  template: {
    type: 'template',
    content: '\n
{{ msg }}
\n'
, start: 10, attrs: {}, end: 54 }, script: { type: 'script', content: '\n' + 'export default {\n' + ' data () {\n' + ' return {\n' + " msg: 'Hello world!'\n" + ' }\n' + ' }\n' + '}\n', start: 77, attrs: {}, end: 174 }, styles: [ { type: 'style', content: '\n.example {\n color: red;\n}\n', start: 194, attrs: {}, end: 236 } ], customBlocks: [ { type: 'custom1', content: '自定义块', start: 257, attrs: {}, end: 261 } ], errors: [] }

通常用于 SFC 构建工具,如 vue-loader、vueify等

compiler.generateCodeFrame(template, start, end)

高亮展示 start,end 代码段。

compiler.generateCodeFrame(`上述代码`, 15, 20)
1  |  <template>
2  |      <div class="example">{{ msg }}</div>
   |      ^^^^^
3  |    </template>

简介解析过程

入口文件 src/compiller/index.js

// 生成ast语法树
const ast = parse(template.trim(), options)
// 标记静态内容(以免diff的时候需要重复比较)
optimize(ast, options)
// 生成 render function code
const code = generate(ast, options)

vue-loader

webpack loader for Vue Single-File Components.
用于 Vue 单文件组件的 webpack 加载器。

Vue Single-File Components

*.vue 文件是一种自定义文件格式,使用类似于 HTML 的语法来描述 Vue 组件。每个 *.vue 文件都包含三种类型的顶级语言块: