DEV Community

Cover image for Vue 3.0 is finally out!

Vue 3.0 is finally out!

jeferson_sb profile image Jeferson Brito Updated on ・6 min read

The new major version of Vue is here! after 2 years of development one of the most popular JavaScript frameworks is full of new capabilities and much more approachable for large applications.

We will go through some of the exciting new features and see how the new release will affect the way you write Vue Apps

Table of contents

Breaking changes

  • Vue 3 has a new Global API, now we use createApp instead of new Vue({})
  • No more support for Filters, you should use computed proprieties or methods instead.
  • $on, $off, and $once methods are removed, you probably have used them before with an eventBus
  • data option should always be declared as a function
  • defineAsyncComponent is the new method used to import and deal with async components
  • Vue's Reactivity system is now based in ES2015 Proxies

How to Create a new Vue 3 App

The most simple way is to just plug in a cdn script tag

     <div id="app">
       <p>{{ message }}</p>
    <script src=""></script>
        const app = Vue.createApp({
          data() {
            return {
              message: 'I love Vue <3',
Enter fullscreen mode Exit fullscreen mode

You can start creating a fresh new Vue 3 App today quickly with the @vue/cli@4.5.0 to take advantage of a toon of integrations that Vue CLI provides out-of-the-box


Alternatively, you can also use Vite, a blazing fast build tool for modern JavaScript Projects, it uses Browser native ES Modules during development combined with Hot Module Replacement, with this approach you only need to bundle the files you actually need and your dev server start fast and cold.

$ npm init vite-app hello-vue3
$ cd hello-vue3
$ npm i && npm run dev
Enter fullscreen mode Exit fullscreen mode

You can learn more about Vite here.

New Global API

Previously in Vue 2.x apps, you would use new Vue() to create a root instance and pass a series of options.
Now with Vue 3.x, we have a new Global API for creating an app instance.

The idea is to everything that mutates Vue's behavior should be placed at the level of the app instance.

// main.js

import { createApp } from 'vue';
import App from './App.vue';

// Create a Vue instance or app
const app = createApp(App)

app.use(/* vue router, vuex, ... */)
app.component(/* some global component... */)
app.directive(/* some custom directive... */)

Enter fullscreen mode Exit fullscreen mode

As you can see every configuration is scoped to a certain Vue application defined with createApp

New Features

Composition API

This is definitely one of the game-changing ones, In fact, Composition API itself deserves a whole article about it, I'll do a quick overview of what it is and how it works.

You may be used to define a new component as an object with a set of options like data, methods, computed, and so on which is perfectly fine for small components, however as your app grows you end up creating complex and large components. Typically in these situations, we create Mixins to extract the common logic to be able to share with other components, which works in some cases but is not very flexible.

Composition API allows us to reuse logic between components creating composition functions, so instead of having your logic split up in multiple component options, you can take advantage of composition functions to have your all your logic code in one place.

In short, with this approach, our components are less complex and much more maintainable.

    placeholder="Enter your favorite game..."
  <button @click="fetchGame">
  <ul v-if="games.results">
    <li v-for="game in games.results" :key="">
      <GameCard :game="game" />
  <p v-if="loading">Loading...</p>
  <p v-if="hasErrors">{{ hasErrors }}</p>

import { ref, computed, onMounted, onUnmounted } from 'vue';
import GameCard from '../components/GameCard.vue';
import useFetch from '../composables/useFetch';

export default {
  components: {
  setup() {
    const searchInput = ref('');
    const { results, hasErrors, loading, execute } = useFetch();

    // Executed when computed is mounted, similiar to Vue 2.x mounted lifecycle hook
    onMounted(() => {

    function fetchGame() {

    // anything that needs to be accessed in the template
    return {
      games: results,
Enter fullscreen mode Exit fullscreen mode

First off, we're importing our components, methods and declaring our setup function.

As you can see we're not using the data() option, in this case we use a ref. A ref is a reactive reference that allows us to track changes in the template.

We're using a composable function called useFetch to handle requests, and last but not least, we returning our state.

Our composable function:

import { ref } from 'vue';

export default function useFetch {
  // reactive state
  const results = ref([]);
  const loading = ref(false);
  const hasErrors = ref(null);

  const execute = async url => {
    loading.value = true;

    try {
      const response = await fetch(url);
      const data = await response.json();
      results.value = data;
    } catch (err) {
      hasErrors.value = err;
    } finally {
      loading.value = false;

  return { results, loading, hasErrors, execute };
Enter fullscreen mode Exit fullscreen mode

You can view this complete example in this repo.

Another good example of Composition API is to create a IntersectionObserver composition function to lazy load our images like so:

// useIntersection.js

import { ref } from 'vue';

export default function useIntersectionObserver() {
  const isSupported = 'IntersectionObserver' in window;
  if (isSupported) {
    const isIntersecting = ref(false);

    const observer = new IntersectionObserver(entries => {
      const component = entries[0];

      if (component.isIntersecting) {
        isIntersecting.value = true;
      } else {
        isIntersecting.value = false;

    const observe = element => {

    const unobserve = element => {

    return { observe, unobserve, isIntersecting };
  } else {
    console.log('Your browser does not support this feature');
Enter fullscreen mode Exit fullscreen mode
<div ref="el">
   :src="isIntersecting ? game.background_image : null"

import { ref, computed, onMounted, onUnmounted, onBeforeUnmount } from 'vue';
import useIntersectionObserver from '../composables/useIntersectionObserver';

export default {
  props: {
    game: Object,
  setup(props, context) {
    const { game } = props;
    const el = ref(null);
    const { observe, unobserve, isIntersecting } = useIntersectionObserver();

    onMounted(() => {

    onBeforeUnmount(() => {

    return { game, el, isIntersecting };
Enter fullscreen mode Exit fullscreen mode


  • Code can now be organized by logical concerns (or features)
  • Keeps your components more readable
  • Extremely flexible

Good news: You can use Composition API with Vue 2 through @vue/composition api module

It's good to say this syntax is optional, therefore you don't need to use composition for every single component you build, the standard object syntax is still completely valid.

Better TypeScript support

Vue 3 is completely written in TypeScript, which is good for everyone, now you can get better type definitions, develop more maintainable apps and, of course, you get the Intellisense and Autocompletetion of your favorite code editor


Suspense is a native Vue component to deal with async dependencies. It is a good option to control what should render until a condition is met and our async component is ready.

In addition, it is a better way to handle multiple API calls from different components than relying on a v-if loading condition.

Note: Suspense is pretty experimental at this stage and its API might change in the future.

    <template #default>
      <GameList /> <!-- or Whatever async component you want to render -->
    <template #fallback>
      Loading ...
Enter fullscreen mode Exit fullscreen mode


We can use Teleport to write components that can be moved/teleported into different parts of your application, by selecting where (DOM element) to place even if this place is not where your app is mounted.

alt Goku teleport

Teleport re-uses the DOM elements, so the state is preserved.

<div id="app"></div>
<div id="move-to-here"></div>
  <teleport to="#move-to-here">
    This should live outside of #app
Enter fullscreen mode Exit fullscreen mode

And you can select the target element in many ways

<teleport to="#id">
<teleport to=".class">
<teleport to="[data-modal]">
Enter fullscreen mode Exit fullscreen mode

Simple, but very powerful!


If you used React before you might know this one, in Vue 2.x we could not create a template with 2 elements at the same root and the reason for that is Vue instance that represents any Vue component needs to be bound into a single DOM element.

Now with Vue 3 you don't have to worry about that

<!-- Before -->


<!-- After -->

Enter fullscreen mode Exit fullscreen mode

Further reading

I'm very glad you reach until here and I hope you enjoyed reading 😊.

Here are some useful links to explore and learn more about Vue 3 🖖

Example shown in this post →

Vue 3.0 current status →

Migration Guide →

Great collection of composable functions →


Editor guide
lexiebkm profile image
Alexander B.K.

Is Vue 3 officially released or still in Preview stage ?
I just started learning Vue, but when reading the doc, I now have to be aware of which version I read. I prefer Vue 3 with its new way of creating app instance as well as new features.
I like it incorporates refs and fragments that I have been familiar and used in React app.

jeferson_sb profile image
Jeferson Brito Author

yes, it's officially released and currently on v3.0.2 now
The docs for Vue 3 are in

Others libraries like vue-router and vuex are still in beta
but you can start using them as well.

More details in

lexiebkm profile image
Alexander B.K.

Thanks for reply
I have read Vue 3 doc, that's why my interest in learning Vue increased. But when I used Vue CLI for creating a simple, basic SPA, the CLI prompted presets option for Vue 3 like so : Vue 3 Preview.
So I thought Vue 3 was still in Preview stage.
However, now I don't care much for this, because I still want to try Vue 3 despite still in Preview stage.

mbokil profile image

The new Vue 3 is very nice. I have been testing it out and the performance is very nice. I have to wait though until they finish the IE11 compatibility since I have customers that need it. The composition API is excellent way to reuse code instead of messy mixins. It also simplifies writing larger components.

hqjs profile image

Try smart web server and a build tool it supports Vue 3 out of the box.

gspace24888670 profile image

Eagerly waiting for this update!
Music streaming app with Django + vuejs + Django rest framework + jwt

peoray profile image
Emmanuel Raymond

Great article. Can't wait to start using it in production

sunitk profile image
Sunit Katkar

Thanks for the article. Will try out Vue 3.

octaneinteractive profile image
Wayne Smallman

Hi Jeferson, I'm still using Vue 2 for a major project and I was wondering if installing Vue CLI 4.5 would break it.