Compiling Vue 3 from scratch and trying the new Composition API
This is the app we will be building:
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.
Getting and Compiling Vue 3
To get started with Vue 3, clone the
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
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:
-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
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
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
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
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
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.
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 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.
Info to use the new
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
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.
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.
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
classcomponent with lifecycle methods, and other use
functioncomponents 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 🤷♂
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.
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.