What's new in Vue 3.1?
Vue 3.1.0 is here!
It has already been 8 months since v3.0.0, and here is the first minor version. In the meantime, 11 patch releases landed mainly with bug fixes and performance improvements, but also with some features and changes.
Let’s catch up with everything that happened since v3.0.0!
Migrate your Vue 2 app with @vue/compat
The main feature of this v3.1 release is the “migration build”. It allows to build and run a Vue 2 application with Vue 3 in a “compatibility” mode. This is an impressive engineering feat, as Vue 3 is a complete rewrite of Vue 2. It has some limitations, and all libraries won’t work (especially if they use internal APIs), but it can help developers migrating their applications progressively.
To give it a try,
you can remplace your Vue 2 dependency by Vue 3.1,
and replace vue-template-compiler
by @vue/compiler-sfc
.
Then you’ll need to add @vue/compat
,
the new package in charge of the compatibility, introduced in v3.1.
You’ll also need to start the application in compatibility mode,
by updating your Vue CLI, Vite or Webpack config.
In Vue CLI for example, you need to add in vue.config.js
:
module.exports = {
chainWebpack: config => {
config.resolve.alias.set('vue', '@vue/compat')
config.module
.rule('vue')
.use('vue-loader')
.tap(options => {
return {
...options,
compilerOptions: {
compatConfig: {
MODE: 2
}
}
}
})
}
}
This will resolve the vue
imports to the new @vue/compat
package,
which know which Vue 3 API is the equivalent of the Vue 2 API you use.
You can then start the application!
When running the Vue 2 application with Vue 3, you’ll see warnings explaining what you’ll need to change to use the Vue 3 modern APIs instead of the deprecated Vue 2 ones.
For exemple, the components defined with Vue.extend
trigger the warning:
[Vue warn]: (deprecation GLOBAL_EXTEND) Vue.extend() has been removed in Vue 3. Use defineComponent() instead.
Details: https://v3.vuejs.org/api/global-api.html#definecomponent
You can then resolve the warnings one by one,
or you can also temporarily silence them using configureCompat
:
Vue.configureCompat({
GLOBAL_EXTEND: 'suppress-warning'
})
You can check out more details in the README of the package: vue-compat
The initial plan for Vue 3.1 was to include other features, but in the end, it was decided to cut a release to let developers experiment with this migration build. This is really interesting if you have Vue 2 applications that you want to migrate 🚀.
IE 11 will not be supported in Vue 3
The original plan was to introduce support for IE11 in Vue 3.1. But, after some considerations and a discussion with the community in the rfcs repository, the team decided not to support it. IE11 has a very small global usage, and a lot of the popular frameworks, libraries, and tools have stopped supporting it as well. Supporting IE11 in Vue 3 would have requested a lot of work (as IE11 does not support Proxies that Vue 3 uses for its reactivity system).
The plan is now to introduce Vue 3 features in the upcoming Vue v2.7, allowing developers that need IE11 support to stay on Vue 2 and enjoy some of the features of Vue 3.
SFC online playground
Evan built a very nice online playground for Single File Components: sfc.vuejs.org. This is very handy to quickly check something, or reproduce an issue!
Experimental setup
Vue 3 has several ways to declare a component. You can use the Options API (which is the API used in Vue 2), but the new and recommended way is to use the Composition API.
<script>
import { defineComponent, ref } from 'vue';
export default defineComponent({
name: 'NavBar',
setup() {
const navbarCollapsed = ref(true);
function toggleNavbar() {
navbarCollapsed.value = !navbarCollapsed.value;
}
return { navbarCollapsed, toggleNavbar };
}
});
</script>
A feature of Vue 3.1 lets you write the same component with the “Experimental setup” syntax:
<script setup>
import { ref } from 'vue';
const navbarCollapsed = ref(true);
function toggleNavbar() {
navbarCollapsed.value = !navbarCollapsed.value;
}
</script>
As you can see, adding the setup
attribute to the script
element
allows to directly declare what you need in the template
and remove the boilerplate.
You can check out the RFC to learn more. The SFC playground supports this syntax, so you can try this example directly in your browser.
A syntax sugar can be used for ref
as well.
This is documented in another RFC
<script setup>
ref: navbarCollapsed = true;
function toggleNavbar() {
navbarCollapsed = !navbarCollapsed;
}
</script>
Check out the online demo.
As this is still very fresh (and has a few remaining issues),
we prefer to stick to the Composition API with a setup
function for now,
but this is exciting for the future.
CSS variable injection
Another RFC has been implemented
and is available as an experimental feature: CSS variable injection.
This allows to directly use the component state inside the style of the component with v-bind()
:
<script setup>
import { computed, ref } from 'vue'
const size = ref(12);
const fontSize = computed(() => `${size.value}px`);
</script>
<style>
h1 {
font-size: v-bind('fontSize')
}
</style>
Check out the online demo and see how the title font size changes automatically.
onServerPrefetch
For those of you working with server-side rendering,
a new onServerPrefetch
lifecycle function is now available.
It is the Composition API equivalent of serverPrefetch
that was introduced in Vue 2.6.
This indicates the server renderer to pause the rendering until the promise it returns is resolved.
Super handy when you want to fetch asynchronous data during the server-side rendering process!
Note that you can call it several times in the same setup,
and they will called in parallel.
<script>
import { defineComponent, onServerPrefetch, ref } from 'vue';
import { getActiveUsers } from './users';
export default defineComponent({
name: 'Home',
setup() {
const activeUsers = ref(0);
onServerPrefetch(async () => {
activeUsers.value = await getActiveUsers()
})
return { activeUsers };
}
});
</script>
BigInt
It is now possible to use BigInt
as a prop type and in the templates directly:
<template>
<h1>{{ size + BigInt(13) }}</h1>
</template>
<script>
import { defineComponent } from 'vue';
export default defineComponent({
props: {
size: BigInt
}
})
</script>
Ecosystem updates
The ecosystem is catching up with Vue 3, and most libraries now offer a compatible version.
The router v4 has been stable for a few months, and offers a nice Composition API.
The Devtools are still in beta for Vue 3, but have some really nice features. They offer a plugins system (handy for the router, vue-i18n, or vuex), a timeline of events with screenshots, suspense and provide/inject support, etc. They now support Vue 2 as well. Vue 3.1 also exposes performance metrics that the devtools can display! It is now super easy to spot if a component takes too much time to render.
Vue CLI v4 already supports Vue 3 and version 5 should be out of beta soon with Webpack 5 support (come back here when it will be out, as we already have a draft blog post about that).
Volar, a VS Code extension and a command line tool to check your templates, is making very good progress. We are now using it in some of our projects with great success, and we can now enjoy template type-checking at compile time.
Vue Test Utils is still in RC, but should be stable fairly soon.
TypeScript support
Vue 3 now supports (and requires) TypeScript v4+ (if you use TypeScript of course, but ain’t that the best way to build a Vue app nowadays? 🤗). It is also now possible to declare your global components, to help tools understand your templates. This is still very early days, but you can now write:
import { RouterView } from 'vue-router'
declare module '@vue/runtime-core' {
interface GlobalComponents {
RouterView
}
}
This lets third-party tools like Volar know that RouterView
is available in your application 😍.
The next release will be v3.2 and should be out in a few weeks or months with new features (initially planned for v3.1). Stay tuned!
All our materials (ebook, online training and training) are up-to-date with these changes if you want to learn more!