问题复现
研究 Vue 3 写 demo 的时候,为求简便直接在当前文件写子组件,用了 template 选项,于是报错了:
const BaseInput = {
template: `
<div>
<p>我是 base input</p>
<input ref="input" />
</div>
`,
...
}
[Vue warn]: Component provided template option but runtime compilation is not supported in this build of Vue. Configure your bundler to alias "vue" to "vue/dist/vue.esm-bundler.js".

最佳方案是用渲染函数替代,render 选项优先级本就高于template
:
注意 ⚠️我安装了 Babel 插件:npm i @vue/babel-plugin-jsx -D
才可以在渲染函数中直接使用JSX
const BaseInput = {
render() {
return (
<div>
<p>我是 base input</p>
<input ref="input" />
</div>
)
},
}
虽然已经明明白白告诉我们要Configure your bundler to alias "vue" to "vue/dist/vue.esm-bundler.js"
,还是继续说说报错的原因和如何能让template
选项正常使用吧。
原因
在 vue npm 包的 dist/ 目录下能找到很多不同的 Vue.js
构建版本。根据项目中 Vue
的集成方式,会使用对应的 js 文件:

比如我是用 Vue Cli 搭建的项目,内部使用 webpack 构建工具。针对这一情况可以使用的是 vue(.runtime).esm-bundler.js,默认是 仅包含运行时的vue(.runtime).esm-bundler.js
。

下面圈出的就是我们的问题所在了:

再通过下面👇运行时 + 编译器 vs. 仅运行时的说明,template
选项的模版字符串不能由runtime
编译,而是需要有编译器的完整构建版本。
而*vue
SFC 组件中<template>
会由 vue-loader 预编译成 JS(Vue Cli 已经默认配置好了),所以不需要编译器,用运行时版本可以节省应用体积。

解决
特别 easy,只要在项目根目录下的vue.config.js
配置一个属性runtimeCompiler: true
,表示使用包含运行时编译器的 Vue 构建版本,然后重新运行就可以了(生产环境别忘了注掉)。
现在就可以在 Vue 组件中使用 template 选项了。

runtimeCompiler 为我们做了 vue 构建版本配置,即像报错提示一样为vue$
设置了文件具体解析地址。

和我们这样手动配置是一样的:
// vue.config.js
module.exports = {
chainWebpack: config => {
config.resolve.alias.set('vue$', 'vue/dist/vue.esm-bundler.js')
},
// runtimeCompiler: true,
}
还有关于运行时编译器的选项 compilerOptions,可以了解下。
举 🌰:compilerOptions.isCustomElement 可以指定一个方法来识别 Vue 以外 (例如通过 Web Components API) 定义的自定义元素。如果组件匹配了这个条件,就不需要再进行本地或全局注册,Vue 也不会抛出 Unknown custom element
的警告。
它替代了 config.ignoredElements 。
// 之前
Vue.config.ignoredElements = ['my-el', /^ion-/]
// 之后
const app = createApp({})
app.config.compilerOptions.isCustomElement = tag => tag.startsWith('ion-')
任何以 'ion-'
开头的元素都会被识别为自定义元素。
私以为虽然是小问题,也要知其然知其所以然。那么当碰到类似的问题,就算库的集成方式不同/
或者换了一种构建工具,也能很快知道排查解决的方向。
如果每次碰到 bug 都是一通百度然后依样画葫芦,那么以后每一次也都要百度。
网友评论