Vue 3 Alpha Has Started!

Mario Brendel
4 min readJan 3, 2020

--

Yes, it is true :). The alpha has officially started as you can read here: https://github.com/vuejs/vue-next. But how can you start and how can you use Vue 3 yourself?

Vue 3 Setup

Evan You (the mastermind behind Vue) was already kind enough to provide a working example for Vue. You can find the example here: https://github.com/vuejs/vue-next-webpack-preview

Let us quickly take a look at what is required to get the project up and running.

Dependencies

If you take a look at the package.json you will see 3 very important packages

"dependencies": {
"vue": "^3.0.0-alpha.1"
},
"devDependencies": {
"@vue/compiler-sfc": "^3.0.0-alpha.1",
"vue-loader": "^16.0.0-alpha.1",
...
}

The first dependency is obviously the new Vue alpha containing all the new cool things like the composition API.
The second one is the compiler-sfc. This is the compiler for single file components (basically your .vue files). I’m not sure if this dependency is actually necessary since the vue loader (which is the 3rd dependency) already contains the compiler-sfc. I would guess that the sfc compiler is only used if you want to create plugins or similar stuff to interpret the single file components. In my opinion, this can be really powerful later on.

Last but not least we have the vue loader. This dependency ensures that our single file components actually work.

Webpack.config.js

Nothing too spectacular here. The only important line is:

{
test: /\.vue$/,
use: 'vue-loader'
},

To ensure that the vue loader is actually used. The rest is your typical Webpack config madness.

Main.js

The main.js has changed a little bit since Vue 2. Instead of writing new Vue you will now create your app via the {createApp} method from the vue package. The main.js consists of the following lines:

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

export const app = createApp();
app.mount(App, '#app');

If we take a closer look at our app object we will notice that this isn’t cluttered with functions anymore. The API is way more readable now than in Vue2. You don’t know what I mean? Just take a look at the new API.

export declare interface App<HostElement = any> {
config: AppConfig;
use(plugin: Plugin, ...options: any[]): this;
mixin(mixin: ComponentOptions): this;
component(name: string): Component | undefined;
component(name: string, component: Component): this;
directive(name: string): Directive | undefined;
directive(name: string, directive: Directive): this;
mount(rootComponent: Component | {
new (): ComponentPublicInstance<any, any, any, any, any>;
}, rootContainer: HostElement | string, rootProps?: Data): ComponentPublicInstance;
provide<T>(key: InjectionKey<T> | string, value: T): this;
}

With Vue 2 the Vue object was a powerhouse of functions. You could either create a new instance by using new Vue({}) or supply plugins by Vue.use or use different helpful functions like Vue.set, Vue.delete, Vue.observable. I’m glad that this has changed and the concerns are now separated more.

App.vue

Lastly, we have our App.vue file. This already uses the new composition API as you can see here:

import {ref} from 'vue'

export default {
setup() {
const count = ref(0)
const inc = () => {
count.value++
}

return {
count,
inc
}
}
}

So what is happening here? We now only have one hook method called setup(). All the other components of a Vue instance will now be handled by functions (at least as long you want to use the composition API)

Within the setup() we have a ref that is needed to observe a given state. This way Vue knows when to rerender parts of the UI. Basically everything that is either within ref or reactive (another Vue function) is similar to the data() component from Vue2.

Lastly, we have a function to increment the count variable. As you can see we use the value property of our count variable. You have to do this so that the observer on the variable don’t vanish. To understand what I mean let’s take a look at the return value of ref(0).

{
value: 0
_isRef: true
get value: ƒ value()
set value: ƒ value(newVal)
__proto__: Object
}

So writing count++ instead of count.value++ would only lead to a syntax error.

Now we only have to return our properties/functions so that the template can evaluate them.

Why Will Vue 3 Be A Lot Better Than Vue 2?

Besides the fact that the APIs are already way more readable, I guess the main feature will be the composition API. But not for the reasons that you might have already heard.

A lot of people say that clustering your logic within the Vue files will provide more readability. While I partially agree I don’t think that this will be the main feature of the composition API. As someone who has already designed architectures with Vue on an enterprise-level, I can tell you that the logic within the Vue files mostly isn’t the problem. The main problems often arise from frameworks like Vuex and the ecosystem surrounding our single-file components. To get the reactivity that Vue provides you are deeply encapsulated into the Vue components itself. So building your own Vuex store can be a real hassle. Gladly Vue 2.6 already provided the Vue.observable function that can turn a given object into an observable object.

With Vue 3 we finally also get the watcher and everything else without being dependent on the Vue instance itself. This way it will be way easier to create new Vue Plugins. In my next blog entry, I will show you how you can build your own Vuex store in Vue 3 with only a couple of lines :).

Can I Use Typescript Already?

Yes, you can use it partially. I’m not sure whether it is available within the .vue files itself but you can write your service classes with typescript and import than into your .vue files.

Example:

AppService.ts

class AppService {
render() {
console.log("render");
}
}

export const appService: AppService = new AppService()

App.vue

...
import {ref, reactive} from 'vue'
import {appService} from "./service/AppService";

export default {
setup() {
const foo = reactive({test: "test"})
const count = ref(0)
const inc = () => {
appService.render()
count.value++
}
...

If you have any questions left or you might want to see how you can already implement some stuff in Vue3 please let me know :).

--

--