fbpx

What You Need to Know About Vue3 in 2020

what you need to know about vue3 header image

VueJS is one of the hottest frameworks in frontend development right now, doubling its weekly download rate in 2019.

The release of Vue3 early in 2020 should only increase its popularity.

While a primary focus of the Vue team was keeping the framework super approachable for all developers, the new version is still super powerful and efficient. There are tons of under-the-hood optimizations that make our lives better.

Vue3 also gives developers way more control (if they want it). It gives us the ability to control exactly what’s happening in our projects from writing custom compile and render methods all the way to directly exposing the Vue reactivity API.

Below are some of the biggest changes that are planned to come according to several of Evan You’s talks and also from the RFC (request for comments) Github repo.

Table of Contents

  1. Vue3 Uses Proxy Based Observers
  2. Composition API
  3. Suspense Components
  4. Component Fragments
  5. Portal Components
  6. Vue3 Rendering Optimizations
    1. Block Tree Optimizations
    2. Aggressive Static Tree Hoisting
  7. Typescript Support
  8. Super Lightweight (Tree Shaking)
  9. Additional Vue3 Resources
  10. Conclusions

Vue3 Uses Proxy Based Observers

Reactivity is the core of VueJS. It’s necessary that data is able to have dependencies, observe them, and update to reflect any changes,

Vue2 uses Object.defineProperty to create getters and setters to create reactivity.

There are two primary issues with using Object.defineProperty – in fact, they’re big enough that they’re even mentioned in the official documentation.

  1. Reactive properties cannot by dynamically added/removed
  2. There are 2 issues dealing with dynamic arrays
    1. Setting an item by accessing via index is not reactive
    2. Modifying the length of an array is not reactive
// Setting an item by accessing via index - NOT REACTIVE
vm.items[indexOfItem] = newValue 

// Modifying the length of an array  - NOT REACTIVE
vm.items.length = newLength

Why Proxy Based Observers?

Vue3’s solution is using Proxy Based Observers to remove the functional limitations from the reactivity system.

A key difference between the old and new systems is that in Vue2, Object.defineProperty mutates the original data whereas Proxies does not. It instead virtualizes the target data and sets up different handlers, called traps, that intercept the data via getters and setters.

This new system means that reactive properties can be added/removed without having to use vm.$set. It also eliminates the Vue2 invalid corner cases when working with arrays.

As best summed up by Evan You’s own Medium post, proxy based observers can now support:

  • Detection of property addition / deletion
  • Detection of Array index / .length mutation
  • Support for Map, Set, WeakMap and WeakSet

There is an excellent overview on VueMastery on how proxy based observers are an improvement.


Introducing the Composition API

This is by far the most well known change coming in Vue3. It should help with code organization and reusability.

Currently, if you’ve done any work in Vue, you’ve been using what is called the Options API. The Options API organizes code by properties: data, computed, methods, and so on.

While this is a super intuitive system and is a something that drew thousands of people to try VueJS, it became very hard to maintain huge components. Code for a single feature was thrown in several places often hundreds of lines apart.

Maintainability and readability became major issues.

Let’s take a quick look at how the Composition API works.

import { reactive, computed } from 'vue'
export default {
   setup() {
		// vue composition api exposes the vue core reactive capabilities
		let state = reactive({
			input: "",
			groceries: [],
			groceriesLeft: computed(() => groceries.length)
		});

		function addGrocery() {
			state.groceries.push(state.input);
			state.input = "";
		}

		function deleteGrocery(index) {
			state.groceries.splice(index, 1);
		}

		return { 
			state, 
			addGrocery, 
			deleteGrocery 
		};
   }
}

Let’s go bit by bit and break down what’s happening.


import { reactive, computed } from 'vue'

The Vue Composition API exposes a lot of the core functionality in Vue such as reactivity and component methods. So, we have to import them.

export default {
   setup() {

The introduction of the setup() method is one of the biggest changes in Vue3. Essentially, it allows us to determine what is passed back to the template. Whatever it returns is accessible in the template.

We can set reactive data, lifecycle hooks, computed properties, defined methods and return whatever we want.

let state = reactive({
	input: "",
	groceries: [],
	groceriesLeft: computed(() => groceries.length)
});

By wrapping all of this data in the reactive method, it all internally becomes reactive. This state pattern comes from the Composition API documentation.

One thing to note is the way we declare the groceriesLeft variable. As you can see, it’s a computed property and is defined right in the setup() method. No more separate computed options property!

function addGrocery() {
	state.groceries.push(state.input);
	state.input = "";
}

function deleteGrocery(index) {
	state.groceries.splice(index, 1);
}

These are just your typical old functions. The only really unique thing is the fact that since all of the reactive data is stored in the state object, we have to access it with the state object. But that’s not Vue3 specific – it’s just your normal Javascript object stuff.

return { 
	state, 
	addGrocery, 
	deleteGrocery 
};

Finally, we want to return these functions from the setup() method. This makes the data and methods accessible inside the template. Thankfully, the template code is still fairly similar.


When this was first introduced, there was tons of backlash in the Vue community because people did not want to be forced to rethink their entire development strategy. However, we have since been assured that this change is purely additive and people can still use the Options API without any problems.

If you want to start getting practice, you can already use the Vue Composition API in your projects.


You Can Now Use Suspense in Vue

Suspense is a feature of React that is now coming to Vue3. It allows your component to display fallback content until your page is ready and all your content is loaded.

This is useful when you want to asynchronously load content in your setup() method. Looking at the Vue-Next repository, it seems that setup() is an async method that returns a Promise. This Promise is caught by the Suspense component which will render fallback content until it is resolved.

Suspense will be useful for…

  • Creating loading pages
  • Waiting for API calls to resolve
  • Really any sort of data fetching or async setup

This will likely be super simple to implement as well, all you would have to do is wrap your code in a Suspense component and define your main content vs. your fallback content.

<Suspense>
  <template >
    <Suspended-component />
  </template>
  <template #fallback>
    Fallback Content
  </template>
</Suspense>

If you want to start see more about how Suspense works and when you might want to use it, check out this VueSchool article.


Fragments are in Vue3 Too

Fragments are root-less components. In Vue2, every component must have one and only one root component.

This can be a headache.

There are several use cases where having a component return several child elements would simplify things. For example, let’s take an example from React and say you have a table structure with a custom component called Columns.

<table>
        <tr>
          <Columns />
        </tr>
 </table>

In order for the compiled HTML to be valid, Columns would need to return several <td> elements. But currently, Vue components need to have a single root element.

The Columns template might look like this, which would cause issues.

<div>
        <td>Hello</td>
        <td>World</td>
</div>

This is where Fragments come in handy. They allow you to return multiple elements which makes cases like these super simple.

A Fragment component in Vue3 might look like this.

<Fragment>
        <td>Hello</td>
        <td>World</td>
</Fragment>

Then, because this would return two <td> elements, the table would be valid and this would be the final result.

<table>
    <tr>
         <td>Hello</td>
        <td>World</td>
    </tr>
 </table>

Perfect.

Currently, there is an unofficial Vue Fragment library that uses internal directives to takes all of the children of a component and moves it into the proper place.


Oh. And Also Portals

Portals are another feature that is natively included in React that is now planned to be implemented in Vue3.

Portals allow you to send content across components meaning that you can edit content that is outside the scope of your current component.

This is extremely helpful when you want to send data to a popup, sidebar, or anything similar.

Like Fragments, there is currently an unofficial portal-vue library that brings that functionality to Vue2. According to the vue-next repo, Portals will be included in Vue3.

Here’s an example screenshot and code from the portal-vue documentation.

example screenshot from the portal-vue documentation
<template>
  <div>
    <div>
      <p>
        The content below this paragraph is
        rendered in the right/bottom (red) container by PortalVue
      </p>
      <Portal to="right-basic">
        <p class="red">
          This is content from the left/top container (green).
          The cool part is, it works across components,
          so you can send your content anywhere!
        </p>
      </Portal>
    </div>
    <PortalTarget name="right-basic"></PortalTarget>
  </div>
</template>

It’s still unclear exactly what the syntax/usage in Vue3 will be, but it should be somewhat similar to this.


Vue3 has Optimized Rendering

A huge part of Vue3 was making it way faster and more efficient. In fact, according to Evan You’s talk at VueConf Toronto, internal tests have shown that template style in Vue3 is ~120% faster than Vue2. 

There were two key optimizations that helps improve Vue3 render speed:

  1. Block Tree Optimizations
  2. Static Tree Hoisting

Let’s go into a little bit more detail about each.

Block Tree Optimizations

Using a Virtual DOM has a natural bottleneck because every component has to track its dependencies.

Observing these dependencies is very slow because it recursively checks the whole element tree to detect changes.

One thing the Vue team noticed was that in components, much of a node’s structure was static. And if a section was in fact dynamic (because of a v-if or v-for directive), then a lot of content inside it was static.

vue3 optimized rendering diagram

Using this idea, Vue3 partitions the template into static vs. dynamic sections. Now that the renderer knows what nodes are dynamic, it doesn’t waste time checking static nodes for changes.

This greatly reduces the number of elements that need to be reactively watched.

Combining all these nodes creates a Block Tree or a template divided into node blocks based on directives (v-if, v-for).

In a block tree, each node has:

  • A fully static node structure
  • Static content that does not need to be watched
  • Dynamic nodes that can be stored in a flat array
illustration of a block tree

This eliminates the need to recursively check every single element, drastically improving runtime.

Static Tree Hoisting

While static tree hoisting is not new (it exists in Vue 2.0), Vue3 has much more aggressive techniques to improve project speeds. As the name suggests, static tree hoisting does not re-render static elements that do not have any dependencies. Instead, it reuses the same element.

This greatly reduces the work of the virtual DOM and saves a lot of project overhead, primarily garbage collection.

In Vue3, static hoisting is much more aggressive in order to work as efficiently as possible.


Typescript Support

Another change coming is that the Vue codebase will be rewritten using Typescript. Once again, a major concern was that forcing people to learn Typescript would increase Vue’s barrier of entry.

So the Vue Team made it easy on us: if you want Typescript, use it; if you don’t, stick with Javascript. Both work just fine.

example code written in both typescript and javascript

If you’re like me, you may be asking “Why Typescript?” and after listening to You’s talk, I’m on board the hype train.

Among other things, Typescript allows you to add type information to your Javascript vars. This alone will greatly help you maintain projects in the long run.

Plus, when working in IDEs that support Typescript, there will be auto-complete and type information available while developing.

According to You, the fact that Vue will be written in Typescript will benefit developers even if they continue using Javascript.

Since the new Vue codebase uses Typescript, there will still be autocomplete, type information, and eventually documentation right from your IDE even while writing Javascript. This will save so many visits to the Vue documentation.


It’s Super Lightweight

Currently, VueJS is already small (20 kb gzipped). But, the Vue team was faced with a problem: new features increased the bundle size for every user regardless if they use it or not.

To fix this, Vue3 will be a lot more modular. While this increases the number of imports you will need to develop, it ensures that you do not have unused libraries in your project.

Thanks to tree shaking (eliminating non-vital code), the estimated size for Vue 3.0 is roughly 10 kb gzipped. Of course, a lot of libraries will be reimported, but it’s great that we’re not forced to have everything.

picture of decompiled vue3 packages

Essentially, developers will not have to pay for features they never use.


A Few Resources to Start Learning Vue3

Honestly, I think that the Vue Core team does such a good job listening to community feedback and providing constant updates that some of the best places to learn Vue3 is their official posts.

In writing this article, I spent a lot of time on the RFC (Request for Comment) and the vue-next (official Vue3) repositories.

Other Resources:

Are You Ready???

If you have any sort of experience developing in Vue, it’s clear that the updates coming in Vue3 will make it more usable and more powerful.

From rendering optimization to helping developers write more readable/maintainable code, Vue3 seems like it will improve on a lot of the pain points experienced in Vue2.

Hopefully, this article did a good job explaining some of the changes and how they work. I’ll definitely update this article when Vue3 is officially released!

Share Your Thoughts