Compiling Vue 3 from scratch and trying the new Composition API

Lachlan Miller
Vue.js Developers
Published in
6 min readNov 14, 2019
Try Vue 3 RIGHT NOW — by compiling it from scratch using the vue-next repo!

In this article I’ll compile Vue 3 from the latest source and try out some of the new APIs, include the upcoming composition API, all using TypeScript.

This is the app we will be building:

The final app I will build

I’ll also give my opinions on the new composition API after trying it out. You can read the RFC here. The source code for this article is here. Since Vue 3 is still under active development, and not even available on npm yet, some features and APIs may change — this article reflects the current state as of the 14th of Nov, 2019.

Check out my Vue.js 3 course! We cover the Composition API, TypeScript, Unit Testing, Vuex and Vue Router.

Getting and Compiling Vue 3

To get started with Vue 3, clone the vue-next repo: git clone https://github.com/vuejs/vue-next.git. Now, cd vue-next and install the dependencies by running yarn install, then build the packages by running yarn build. This might take a while.

Next, add a basic index.ts:

And index.ts:

Since we will use TypeScript, we will need a few dependencies and a basic webpack.config.js to compile for use in a browser. Install them:

We need -W since we are currently are in a git repository containing several sub packages (in the packages directory, Vue 3 is very modular like that) and we want to install the dependencies to the top level. We will piggyback of the existing tsconfig.json - but we don't want to watch the entire repository during development, since we have already built the project when we ran yarn build earlier. In the existing tsconfig.json, remove all the entires in the "include" array.

Next, I created a webpack.config.js and added the following:

Okay, now we are ready to start hacking. I had bit of trouble getting everything to work — I was really hoping to import a bunch of TypeScript methods and get autocompletion out of the box, but either I didn’t build the packages right or I’m missing something, or it’s just too early for that in development of Vue 3. So we will need some type definitions. The TypeScript experience is, to me, the killer feature of Vue 3, not the new APIs or other features.

Building an App with Vue 3 and TypeScipt

Start by updaing index.ts with the following:

I tried using the definitions generated during the yarn build step earlier, but I couldn't get it working - TS errors everywhere, so for now I just made some minimal types to get us started. We no longer do const app = new Vue(....).$mount('#app') anymore - Vue 3 exposes a createApp function, which returns a mount method to which you pass your root component and selector.

Ideally, we would use tsx in render functions, however I couldn't get that working either, so for now I'll just use string literals with template. In the future, tsx and render functions will be supported, and we should be able to get static typechecking on our templates, like in React when using tsx!

You can see there is now a setup function, which takes the props as the first argument, as shown in the Info component. Since App is the top level component, it does not receive any props. setup returns and object which is what would be saved in data and computed fields in the current Vue 2 API. This will still be an option in Vue 3, as well.

Whatever you return from setup are made available in the template function. I like to define this object as XXXSetup, where XXX is the name of component. It's like a schema for your component; it tells the developer what the setup function's API looks like. Think of it like a form a documentation.

setup is called once, when the component is created for the first time (like the existing created lifecycle method). The above code renders the following entirely uninteresting Vue app:

Let’s explore some more of the new APIs.

Using reactive

Vue now exposes a reactive method. This lets us make any object... reactive. The type definition looks like this, taken from here:

We can update the setup function in App using the new reactive function. reactive takes an object - count is a primitive. You can use another new API, ref, for primitive values, but for now let's use reactive with a count key. This will make it easy to add more reactive properties soon. They are actually slightly difference, you can read more here in the RFC.

Next, update Info to use the new increment function:

Errata: you do not need to return props . Vue automatically makes them available in the template.

Let’s say we want the message prop to be dynamic, based on the value of count. We can use computed. Update the type definition, which in it's basic form is the same as reactive. Also update App:

Now we have two count messages that increment together. Let’s take a look at another familiar API from Vue 2, watch. There are quite a few type overloads if you dig deep into the repo, I'll just demonstrate the simplest here.

Final type definitions for this article
Final App

watch, takes a function, which should reutrn the reactive object to watch. The next argument is a callback which is called when the watched value mutates. The callback receives the newly updated value and the previous value, just as it does in Vue 2.

The final app

This is a pretty basic app, but it does a good job of showing of the new Vue 3 composition API.

Thoughts and Reflection

The new composition API RFC has received mixed feedback from the community. One thing I think is important to remember is the composition API is additive — none of the existing Vue 2 APIs is going away. Here are some of nice things about it, and Vue 3 in general:

  • The entire codebase is in TypeScript, which means we get better type checking and assistance from the IDE.
  • The composition API allows for better Typescript support. I think this is the real killer feature — I don’t have a strong opinion on which API I like better, I just want to have type safety so I can build bug free applications and deliver value to clients.
  • It is certainly a departure from what I first liked about Vue — simple and seemingly “magic” reactivity.
  • Good support for tsx - not my preferred way to write templates, but if it means better type safety, I'll take it.

Some of the cons are:

  • Two ways to write Vue components — just because you know one Vue app well, another might be completely different. This is kind of how I feel about React now. Some codebases use class component with lifecycle methods, and other use function components with the new React hooks. It's a bit tiring to learn so many ways to do the same thing.
  • likely more work to write a plugin supporting two different APIs.
  • You need to learn something new. If you don’t like learning new things, you probably don’t belong in the modern JS world anyway. Not sure if this is a good or bad thing 🤷‍♂

Conclusion

We explored the new composition API and Vue 3 by compiling it from source. Exciting times are ahead!

For more learning resources, I’ve found Vue School to have the best courses. The teachers, Alex and Chris, are core contributors to Vue and the upcoming Vue 3, and have been for many years.

https://vueschool.io/?friend=vth

They were a big help to me when learning Vue. They also have an upcoming Vue 3 master class which I’m looking forward to. Alex mentioned they have a big sale coming up for Black Friday, so check their courses out if you looking for more Vue resources.

Originally posted on my personal blog.

--

--

Lachlan Miller
Vue.js Developers

I write about frontend, Vue.js, and TDD on https://vuejs-course.com. You can reach me on @lmiller1990 on Github and @Lachlan19900 on Twitter.