vue-template-compiler-compat
v0.4.2
Published
Provide compatibility for Vue 2 template compiler
Downloads
11
Maintainers
Readme
vue-template-compiler-compat
Provide compatibility for Vue 2 template compiler.
[!NOTE] This is NOT an official library of Vue.
Installation
npm install --dev vue-template-compiler-compat
Usage
const { compile } = require('vue-template-compiler')
const { createCompatModule } = require('vue-template-compiler-compat')
compile('your template here', {
modules: [
createCompatModule({
model: true,
typescript: true,
}),
],
})
Standalone usage
const { compile } = require('vue-template-compiler')
compile('your template here', {
modules: [
require('vue-template-compiler-compat/modules/model'),
require('vue-template-compiler-compat/modules/typescript')
],
})
For vue-loader
const { createCompatModule } = require('vue-template-compiler-compat')
module.exports = {
rules: {
test: /\.vue$/,
use: [
{
loader: 'vue-loader',
options: {
compilerOptions: {
modules: [
createCompatModule({
model: true,
typescript: true,
}),
],
},
},
},
],
},
}
Modules
model
This module compiles the v-model
syntax from Vue 3 to the format supported by Vue 2.
<template>
<Foo v-model:bar="baz"></Foo>
</template>
<!-- will be compiled to -->
<template>
<Foo v-bind:bar.sync="baz"></Foo>
</template>
It will not affect the v-model
without argument. Although v-model
without argument differs in Vue 3 from Vue 2, we recommend that you use the model
option to shim at runtime, rather than doing it during compilation.
const Foo = {
// This is set up to ensure consistent behavior with Vue 3
model: {
prop: 'modelValue',
event: 'update:modelValue',
},
}
In addition, it will also ignore any modifiers to the v-model
that are compiled. Because the modifier only works for input
elements in Vue 2, however, input
does not support v-model
directives with argument.
For custom modifiers, you can pass them in manually to maintain compatibility between Vue 2 and Vue 3.
<template>
<Foo v-model:bar="baz" :model-modifiers="{ qux: true }"></Foo>
</template>
Solving ESLint Errors
If you are using eslint-plugin-vue
and extend the plugin:vue/essential
, you will need to manually turn off the following rules:
// .eslintrc.js
module.exports = {
rules: {
'vue/no-v-model-argument': 'off',
},
}
Don't worry, it won't cause significant problems because another rule vue/valid-v-model
guarantees the legality of the directive.
typescript
This module helps templates to support the TypeScript syntax.
Before you can use it, you need to make sure that esbuild
have been installed in your project. To make it easier to manage versions, esbuild
or @babel/core
are not included in the dependencies by default.
<template>
<div>{{ foo!.bar }}</div>
</template>
<!-- will be compiled to (for illustration only) -->
<script>
with (this) {
return (function () {
return _c('div', [_v(_s(foo.bar))]);
})()
}
</script>
<template>
<div>{{ foo as (string | number) }}</div>
</template>
<!-- will be compiled to (for illustration only) -->
<script>
with (this) {
return (function () {
return _c("div", [_v(_s(foo))])
})()
}
</script>
Why not provide it as a custom compiler?
Because vue-template-compiler
only supports compilers in object format (not module paths in string), which makes it impossible to share this configuration within threads when using the thread-loader
with the default configuration of the Vue CLI.
syntax
(for vue@<2.7
only)
This module helps templates to support the latest ECMAScript syntax, such as Optional Chaining and Nullish coalescing Operator proposals.
Before you can use it, you need to make sure that either esbuild
or Babel
have been installed in your project. To make it easier to manage versions, esbuild
or @babel/core
are not included in the dependencies by default.
<template>
<div>{{ foo?.bar }}</div>
</template>
<!-- will be compiled to (for illustration only) -->
<script>
with (this) {
return (function () {
return _c('div', [_v(_s(foo == null ? void 0 : foo.bar))]);
})()
}
</script>
<template>
<div>{{ foo ?? bar }}</div>
</template>
<!-- will be compiled to (for illustration only) -->
<script>
with (this) {
return (function () {
return _c("div", [_v(_s(foo != null ? foo : bar))])
})()
}
</script>
By default, this module does not inherit any Babel configuration from the current project.
Why esbuild
is more recommended than Babel?
Simply, to reduce configuration costs. When using Babel as a transformer, not only we should care about the preset or plugin you need to use, but that configuration may become obsolete with new syntax.
Nevertheless, we've also made the Babel-based implementation available as modules/syntax-babel
, which you can use or write your own module based on it. In addition, there is a lower-level modules/syntax-transform
module that completes the syntax compilation process with the help of a custom transformer.
As a reference, the results of my tests on a huge private project are as follows (For Babel, with only Optional Chaining and Nullish coalescing Operator proposals enabled):
- Without transformer: 328.104s
- Using Babel as transformer: 340.078s (+3.65%)
- Using esbuild as transformer: 338.509s (+3.17%)
All the above times refer to CPU time, i.e. not considering multi-core performance.
slot
(Unofficial)
This module provides compatible syntax of slots for Vue 2.6 and previous versions.
Slot data generated with the v-slot
syntax is only available via $scopedSlots
in Vue 2. For some early component libraries (such as element-ui
), this behavior may not be implemented for some components. In these scenarios, we can only use the deprecated slot
syntax, but this is not conducive to migration to Vue 3.
We chose an edge case that matches the syntax of Vue 2.6 and Vue 3, compiling it to the old slot
syntax.
<template>
<Foo>
<template #header slot>
<Bar />
</template>
</Foo>
</template>
<!-- will be compiled to -->
<template>
<Foo>
<template slot="header">
<Bar />
</template>
</Foo>
</template>
Setting the slot
attribute with empty value on a template
element with a v-slot
directive will be ignored in the default compilation syntax. For v-slot
directives on non-template elements, this module will not handle them, since no such compatible syntax exists.
This module works with both the v-slot
directive and its abbreviation #
.
Why not use a directive modifier such as v-slot:foo.compat
?
This is because the vue-template-compiler
actually supports .
symbols in slot names, which means that v-slot:foo.compat
will operate on the foo.compat
slot by default.