Vue --- Runtime + Compiler vs. Runtime-only

学习目标:
一、理解Runtime + Compiler vs. Runtime-only
二、如何设置Runtime + Compiler 和Runtime-only环境
三、理解源码实现原理

理解Runtime + Compiler vs. Runtime-only

一、如果你需要在客户端编译模板 (比如传入一个字符串给 template 选项,或挂载到一个元素上并以其 DOM 内部的 HTML 作为模板),就将需要加上编译器

// 需要编译器
new Vue({
  template: '
{{ hi }}
' })

二、vue-loader 或 vueify 的时候,*.vue 文件内部的模板会在构建时预编译成 JavaScript,则不需要编译器

// 不需要编译器
new Vue({
  render (h) {
    return h('div', this.hi)
  }
})

环境设置

环境默认是 Runtime-only,vue指向的是'vue/dist/vue.runtime.esm.js'
如果想要用有编译器的模式的话,操作如下:
1.在根目录下增加一个vue.config.js
2.vue.config.js的内容是:

module.exports = {
    runtimeCompiler:true
}

问题(理解源码实现原理)

1.vue.config.js 为什么是这个文件名?
2.runtimeCompiler:true这个开关属性是如何控制用编译器文件的?


image.png

问题1:vue.config.js 为什么是这个文件名?

查看Service.js文件:
. 这里的loadUserOptions函数就是用来处理vue.config.js的对象属性的
. 可以看到这个文件中用到vue.config.js或vue.config.cjs这个名字

  loadUserOptions () {
    // vue.config.c?js
    let fileConfig, pkgConfig, resolved, resolvedFrom
    const esm = this.pkg.type && this.pkg.type === 'module'

    const possibleConfigPaths = [
      process.env.VUE_CLI_SERVICE_CONFIG_PATH,
      './vue.config.js',
      './vue.config.cjs'
    ]
    let fileConfigPath
    for (const p of possibleConfigPaths) {
      const resolvedPath = p && path.resolve(this.context, p)
      if (resolvedPath && fs.existsSync(resolvedPath)) {
        fileConfigPath = resolvedPath
        break
      }
    }
......
return resolved
}

上面的return resolved的最后结果显示为:

{runtimeCompiler:true}

问题2.runtimeCompiler:true这个开关属性是如何控制用编译器文件的?

打开文件base.js

      webpackConfig.resolve
        .alias
          .set(
            'vue$',
            options.runtimeCompiler
              ? 'vue/dist/vue.esm.js'
              : 'vue/dist/vue.runtime.esm.js'
          )

上面代码可以看到options.runtimeCompiler如果为true,则用到的是有编辑器的文件'vue/dist/vue.esm.js',否则用到的是runtime即'vue/dist/vue.runtime.esm.js'

问题

现在问题是如何确定options.runtimeCompiler中的options对象中的runtimeCompiler就是vue.config.js文件中的runtimeCompiler
1.查看Service.js

  init (mode = process.env.VUE_CLI_MODE) {
    ......
    // load user config
    const userOptions = this.loadUserOptions()

    this.projectOptions = defaultsDeep(userOptions, defaults())
    ......

    // apply plugins.
    this.plugins.forEach(({ id, apply }) => {
      if (this.pluginsToSkip.has(id)) return
      apply(new PluginAPI(id, this), this.projectOptions)
    })
  }

上面代码我们知道loadUserOptions函数最后返回的就是vue.config.js中的对象

const { defaults, validate } = require('./options')

defaults得到的是./options中的返回对象值

this.projectOptions = defaultsDeep(userOptions, defaults())

this.projectOptions就是把vue.config.js+(./options.js的default)合并到一起的对象即是:

{ 
runtimeCompiler: true,
  publicPath: '/',
  outputDir: 'dist',
  assetsDir: '',
  indexPath: 'index.html',
  filenameHashing: true,
  transpileDependencies: [],
  productionSourceMap: true,
  parallel: true,
  pages: undefined,
  crossorigin: undefined,
  integrity: false,
  css: {},
  lintOnSave: 'default',
  devServer: {} 
}
// apply plugins.
    this.plugins.forEach(({ id, apply }) => {
      if (this.pluginsToSkip.has(id)) return
      apply(new PluginAPI(id, this), this.projectOptions)
    })

其中apply(new PluginAPI(id, this), this.projectOptions)表示执行this.plugins的函数,其中就包含base.js的文件,参数一个是api,一个是options

module.exports = (api, options) => {
......
      webpackConfig.resolve
        .alias
          .set(
            'vue$',
            options.runtimeCompiler
              ? 'vue/dist/vue.esm.js'
              : 'vue/dist/vue.runtime.esm.js'
          )
.......
}

this.projectOptions也就是合并到一起的对象故这里的options.runtimeCompiler中的runtimeCompiler属性也就是vue.config.js中的runtimeCompiler

你可能感兴趣的:(Vue --- Runtime + Compiler vs. Runtime-only)