Vue 2.6 released

Yesterday we just celebrated the 5th Vueniversary — today we are excited to announce the release of Vue 2.6 “Macross”!

In the past year, we spent a lot of time working on the new CLI and prototyping for 3.0. As a result, Vue core 2.x hasn’t received major updates in quite a while. It’s about time! This release combines a number of substantial improvements, internal changes and new features which are highlighted in this post. For full details, make sure to also check out the full release note on GitHub.

Slots: New Syntax, Performance Improvements & Alignment with 3.0

Slots is an important mechanism that enables flexible component composition in Vue. During the prototyping for 3.0 we discovered a number of ways to improve it. Some of these can be introduced without breaking changes, which allows us to ship them in a 2.x minor release. For those that do require breaking changes, we are also trying to provide progressive alternatives in 2.x that would make future migrations easier.

New Syntax

The first step is the new syntax of scoped slots. We proposed, discussed and experimented with a number of different designs (1, 2, 3) and eventually landed on the new v-slot syntax outlined in this RFC. Here is a brief example using named slots:

v-slot usage for a component with multiple named slots

The new syntax unifies the usage of normal and scoped slots in a single directive, and enforces more explicit and readable named slots usage. It is also fully compatible with the existing syntax, which allows us to ship it today in 2.6.

If you are already familiar with the existing slot syntax, we recommend you to read through the RFC to better understand the rationale behind the new syntax. If you are not yet familiar with slots, it is recommended to go through the updated slots documentation instead.

Performance Improvements

Another improvement for slots we would like to see in 3.0 is the unification of normal vs. scoped slots in terms of implementation, due to the performance advantage of scoped slots. Normal slots are rendered during the parent’s render cycle. When a dependency of a slot changes, it causes both the parent and child components to re-render. Scoped slots, on the other hand, are compiled into inline functions and called during the child component’s render cycle. This means any data dependencies relied on by a scoped slot are collected by the child component, resulting in more precise updates. In 2.6, we have introduced an optimization that further ensures parent scope dependency mutations only affect the parent and would no longer force the child component to update if it uses only scoped slots.

In addition:

  • All slots using the new v-slot syntax are compiled into scoped slots. This means all slots using the new syntax automatically get the performance improvements;
  • All normal slots are now also exposed on this.$scopedSlots as functions. This means users using render functions instead of templates can now always use this.$scopedSlots without worrying what type of slots are being passed in.

In 3.0, there will no longer be the distinction between scoped vs. non-scoped slots — all slots will use the same unified syntax, are compiled into the same format, and have the same optimal performance.

Async Error Handling

Vue’s built-in error handling mechanism (in-component errorCaptured hook and the global errorHandler hook) now also captures errors inside v-on handlers. In addition, if any of your lifecycle hooks or event handlers performs asynchronous operations, you can now return a Promise from the function so that any uncaught errors from that Promise chain are also sent to your error handlers. It becomes even easier if you are using async/await, since async functions implicitly return Promises:

Async error handling in lifecycle hook

Dynamic Directive Arguments

Directive arguments can now accept dynamic JavaScript expressions:

Dynamic argument examples

More details can be found in this RFC. Conveniently, if the argument value is null, the binding/listener will be removed.

Note to library authors: this feature requires the Vue runtime to be of version 2.6.0 or higher. If you ship pre-compiled components and want to maintain compatibility with versions before 2.6, avoid using this in your source code.

Code Frame in Compiler Warning Messages

Thanks to the stellar pull request by GitHub user @gzzhanghao, starting in 2.6 most template compilation warnings now comes with source range information. This has enabled us to generate nice code frames for these warnings:

Explicit Creation of Standalone Reactive Objects

2.6 introduces a new global API to explicitly create standalone reactive objects:

The resulting object can be used directly in computed properties or render functions, and will trigger appropriate updates when mutated.

Data Pre-fetching during Server Side Rendering

The new serverPrefetch hook allows any component (instead of just route-level components) to pre-fetch data during server-side rendering, allowing for more flexible usage and reducing the coupling between data fetching and the router. Projects like Nuxt and vue-apollo are already planning to simplify their implementations using this new feature.

ES Module Build for Direct Import

Previously, our ES Module build is primarily intended for use with bundlers. These builds contain usage of environment variables that are meant to be replaced at compile time. Vue 2.6 now also provides an ES Module build that are intended for direct in-browser usage:

Important Internal Changes

Reverting nextTick to Microtask

In 2.5.0 we made an internal adjustment that caused nextTickto use Macrotasks instead of Microtasks to queue updates if the update was triggered in a v-on event handler. This was originally intended to fix some browser edge cases, but has in turn led to a number of other issues. In 2.6 we have found a simpler fix for the original issue, which allows us to revert nextTick to consistently use Microtasks in all cases.

If you are interested in more technical details, check it out here.

Functions on this.$scopedSlots now always return Arrays

(This change only affects render function users.) In render functions, scoped slots are exposed on this.$scopedSlots as functions. Up until now, calling a scoped slot function can return a single VNode or an Array of VNodes based on what the parent component is passing in. This was honestly an oversight as it makes the return value type indeterministic and can lead to unintended edge cases. In 2.6, scoped slot functions are now guaranteed to return either an Array of VNodes or undefined. This may affect some existing code if it is not properly checking for possible Array return values. More details here.

Shoutouts

Thanks to the contributors who contributed pull requests in this release, and to all the community members that participated in the RFC discussions.