Vue.js 使用 runtime only build

新项目中使用 Vue.js,随着开发的推进,对 Vue 的官方文档及源码的阅读和学习也在深入。与 React 的jsx相似, Vue 在底层的实现上,也是将模板编译成虚拟 DOM 渲染函数。而这个编译过程一般通过webpack 等构建工具提前完成,在代码运行时只需要引入runtime版本即可,无需实时编译,否则会对性能造成影响 。

使用 runtime 版本替代带编译器版本

Vue的官方文档中有对 Runtime + Compiler vs. Runtime-only的说明,如果项目中的Vue 实例没有用到 template 字符串或 dom 模板作为选项,则可以引入 runtime 版本的dist 文件,在 webpack 中可以配置一个别名予以简化引入。我们的项目使用了官方的webpack 工程模板(有经过改造),在这里用的还是编译器版本的,于是将其调整为 runtime版本:

1
2
3
4
5
6
7
8
9
module.exports = {
// ...
resolve: {
alias: {
// 'vue$': 'vue/dist/vue.esm.js',
'vue$': 'vue/dist/vue.runtime.esm.js',
}
}
}

使用 render 选项替代 template

项目中的组件模板都是通过单文件组件(*.vue文件)组织的,通过vue-loader已经提前编译成 render 函数,按理说可以使用 runtime 版本,但跑起来始终报 You are using the runtime-only build of Vue where the template compiler is not available. Either pre-compile the templates into render functions, or use the compiler-included build. Debug 发现,原来入口文件main.js中初始化根组件时引入 App组件就用了 template 选项:'<App/>',问题就在这里,改动方法也比较简单,就是将其改为 render 选项:

1
2
3
4
5
6
new Vue({
el: '#app',
components: { App },
// template: '<App/>'
render: createElement => createElement(App)
})

render 选项传入的是一个回调函数,createElement 作为这个函数的参数,其实可以是任意一个有效函数名,但如文档所述,作为通用惯例,可以用h 来替代 createElement

总结

对于runtime版本的使用,官方文档都有详见的描述,但是由于使用了官方的 webpack 工程模板,默认使用了带编译器版本,而且没有对此细节的相关说明,也是踩了一个小坑。虽然官方说实时编译本来也已经很快了,但对大型应用来说,这个性能优化还是有必要的,而且runtime版本比带编译器版本的dist文件小了不少(生产构建版本当然不会差太多),也是能节省一点流量开销。

不过,要使用 runtime 版本得确保组件实例里不存在 字符串template 选项或dom模板,可以根据自己的实际项目需求来定。