text: /* @flow */
  
  import config from 'core/config';
  import { warn, cached } from 'core/util/index';
  import { mark, measure } from 'core/util/perf';
  
  import Vue from './runtime/index';
  import { query } from './util/index';
  import { compileToFunctions } from './compiler/index';
  import { shouldDecodeNewlines, shouldDecodeNewlinesForHref } from './util/compat';
  
  const idToTemplate = cached(id => {
    const el = query(id);
    return el && el.innerHTML;
  });
  // 缓存原有$mount方法
  const mount = Vue.prototype.$mount;
  // 基于原有$mount方法，重写新的$mount方法,新的$mount方法会进行模板编译：compileToFunctions
  Vue.prototype.$mount = function (
    el?: string | Element,
    hydrating?: boolean
  ): Component {
    el = el && query(el);
  
    /* istanbul ignore if */
    if (el === document.body || el === document.documentElement) {
      process.env.NODE_ENV !== 'production' && warn(
        `Do not mount Vue to <html> or <body> - mount to normal elements instead.`
      );
      return this;
    }
  
    const options = this.$options;
    // resolve template/el and convert to render function
    if (!options.render) {
      // 没有render选项
      let template = options.template;
      if (template) { // 有template
        if (typeof template === 'string') {
          if (template.charAt(0) === '#') { // template是id选择器
            template = idToTemplate(template);
            /* istanbul ignore if */
            if (process.env.NODE_ENV !== 'production' && !template) {
              warn(
                `Template element not found or is empty: ${options.template}`,
                this
              );
            }
          }
          // 说明template是html模板，不用处理
        } else if (template.nodeType) { // template是真实dom，获取其innerHTML
          template = template.innerHTML;
        } else {
          if (process.env.NODE_ENV !== 'production') {
            warn('invalid template option:' + template, this);
          }
          return this;
        }
      } else if (el) { // 没有template,但是有el，将el.outerHTML作为template
        template = getOuterHTML(el);
      }
      if (template) { // template为html字符串
        /* istanbul ignore if */
        if (process.env.NODE_ENV !== 'production' && config.performance && mark) {
          mark('compile');
        }
        // 将template编译为render函数
        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;
  
        /* istanbul ignore if */
        if (process.env.NODE_ENV !== 'production' && config.performance && mark) {
          mark('compile end');
          measure(`vue ${this._name} compile`, 'compile', 'compile end');
        }
      }
    }
    return mount.call(this, el, hydrating);
  };
  
  /**
   * Get outerHTML of elements, taking care
   * of SVG elements in IE as well.
   */
  function getOuterHTML (el: Element): string {
    if (el.outerHTML) {
      return el.outerHTML;
    } else {
      const container = document.createElement('div');
      container.appendChild(el.cloneNode(true));
      return container.innerHTML;
    }
  }
  
  Vue.compile = compileToFunctions;
  
  export default Vue;
  