Template compilation

1. The concept

The main goal of template compilation is to convert a template to a render function.

2. Necessity of template compilation

Vue2.0 requires the use of VNode to describe views and various interactions. It is not feasible for developers to write render functions by hand, so developers need to write A Vue template that looks like HTML code and the compiler converts the template into a RENDER function that returns VNode.

3. Output after the template is compiled

In versions with a compiler, templates can be declared using template or EL

with(this) {return _c('div', {attrs: {"id":"demo"}},[_m(0),_v(""),(foo)? _c('p',[_v(_s(foo))]):_e(),_v(""),_c('comp', {on: {"myclick":onMyClick}})],1)}
Copy the code

_c is the createElement alias

There are two time points for template execution :(with or without compiler) 1) precompile before webpack runtime 2) directly introduce vue.js mode, then own compiler, el or template, compile in real time

4. The overall process of vue source template compilation

Template will be compileToFunctions when the $mount entry is mounted

Location: platform/web/entry – the runtime – with – compiler. Js

Function: If the template or EL option is specified, compilation is performed

Vue.prototype.$mount = function (
  el?: string | Element,
  hydrating?: boolean
) :Component {
    const { render, staticRenderFns } = compileToFunctions(template, {
        outputSourceRange: process.env.NODE_ENV ! = ='production',
        shouldDecodeNewlines,
        shouldDecodeNewlinesForHref,
        delimiters: options.delimiters,
        comments: options.comments
      }, this)
      options.render = render
      options.staticRenderFns = staticRenderFns
}
Copy the code

2) Compilation process

Location: SRC/compiler/index. Js

export const createCompiler = createCompilerCreator(function baseCompile (template: string, options: CompilerOptions) :CompiledResult {
  const ast = parse(template.trim(), options)
  if(options.optimize ! = =false) {
    optimize(ast, options)
  }
  const code = generate(ast, options)
  return {
    ast,
    render: code.render,
    staticRenderFns: code.staticRenderFns
  }
})
Copy the code

3) Compile three stages

  • Parse

The parser parses the template into an abstract syntax tree AST, and only after the template is parsed into an AST can it be used to optimize or prop up code strings

Location: the SRC/compiler/parser/index. Js

HTML parser, text parser, filter parser, and the most important HTML parser:

parseHTML(tempalte, {
    start(tag, attrs, unary){}, // Start tag processing is encountered
    end(){},// An end tag is encountered
    chars(text){},// Text label processing is encountered
    comment(text){}// A comment tag is encountered
})
Copy the code

Using the Chrome debugging tool, obtain the AST structure as follows:

  • Optimize

    The optimizer’s job is to find and label static subtrees in the AST. Static subtrees are nodes that never change in the AST, such as plain text nodes.

    Benefits of marking static subtrees:

    • There is no need to create a new node for a static subtree each time you re-render
    • When patch is created in the virtual DOM, static subtrees can be skipped
    <! To create a nested relationship --><h1>Vue<span>Template compilation</span></h1>
    Copy the code

    Location: SRC/compiler/optimizer. Js – optimize

  • Generate

Convert the AST into the content of the rendering function, which is the code string.

Location: the SRC/compiler/codegen/index. Js

code = "_c('div',{attrs:{"id":"demo"}},[_m(0),_v(" "),(foo)? _c('p',[_v(_s(foo))]):_e(),_v(" "),_c('comp',{on:{"myclick":onMyClick}})],1)"

Copy the code