19th June 2018
Vue.js: the good, the meh, and the ugly
Moving from React to Vue, two years later
Picking up new frameworks and libraries is exciting but also stressful. Even after some evaluation you never really know what skeletons you’re going to find out down the road.
My honeymoon period is long over. After about 2 years of using Vue almost daily I can finally write about it with some perspective.
DANGER: Opinions ahead.
The Good
Reactivity
Data binding is a big deal in the front end world. Instead of micromanaging the DOM like we did with jQuery we now focus on data. Vue handles this neatly with a two-way reactive data-binding system.
To achieve this reactivity Vue adds a number of getters and setters to every variable in your state so that it can track changes and update the DOM automatically (cough this.setState()
cough). This approach is not perfect, as we’ll see later.
Batteries included
With Vue there is no need to resort to unofficial packages like MobX or React Router for the critical parts of your application. Vue provides Vue Router and Vuex, a Redux-inspired reactive central state manager. These are great libraries on their own, but the fact that they were custom-designed for Vue makes them even better.
Speed
Vue is really fast. Maybe not the fastest, but its performance is overkill for the vast majority of web projects. When was the last time you needed to render and update thousands of DOM elements per second?
HTML templates
This is a divisive topic among JavaScript developers. Regardless of your preference, HTML templates have been battle tested for decades in many languages and are the primary choice for writing dynamic markup in Vue.
But hey, Vue supports JSX too.
Other goodies
- Single file components with HTML, CSS, and JavaScript.
- Lightweight. Around 20KB (minified + gzip).
- Very extensible (mixins, plugins, etc).
- Great documentation (with some exceptions noted below).
- Can be adopted progressively, even used as a jQuery replacement.
- Easy to get started.
The Meh
Component boilerplate
Moving from React to Vue seems like a breath of fresh air. No more bind(this)
or setState()
everywhere. Yay! But after a while, you start to question the validity of Vue’s component syntax.
Vue components are created with objects and here’s an example of defining a component function:
export default {
methods: {
increment () {
this.count++;
}
}
}
You’ll be adding similar boilerplate for computed properties, component state, watchers, etc. Pretty much everything in Vue has its own special syntax with more boilerplate.
In contrast here’s the same thing for Marko which is way cleaner:
class {
increment() {
this.state.count++;
}
}
My point here is not about using classes or not, but that Vue is using arbitrary object structures instead of language features.
I won’t blame you if you feel a little dirty by having to create these annoying objects. Vue also offers a class based syntax, but it’s really more of an afterthought.
Chat based community
The Vue community hangs out on Discord, a chat designed for gamer communities. If you hit a roadblock the chat is probably your best bet since the official forums are a desolate land, and don’t you dare ask a question on Github.
Chats are messy, but the main problem is that chat content can’t be indexed by search engines. The same questions (and its related discussions) are doomed to be repeated again and again and again.
This trend of using chats for questions is plaguing open source projects and I think it needs to end. There is no collective learning anymore.
Not so magic
As long as you don’t steer away from the golden path everything will be fine, but after some time you will probably find lots of little ifs and buts around Vue.
Some examples:
- The reactivity system will only track changes under certain conditions. Don’t expect to throw anything you wish at it. Quite often you may need to flatten your data as much as possible to avoid headaches. Of course, it’s all explained in the fine print of the documentation.
- The transition system
<vue-transition>
does not work for lists. You actually need to use<transition-group>
which works slightly differently and introduces new elements in your DOM. Also, one would expect staggering to be a solved thing, but you have to implement it yourself. - If you need non-reactive state in a component instance you will be into uncharted territory.
Etc.
Don’t get me wrong, these are not deal breakers, but it seems every time you start scratching the surface another minor annoyance pops up.
The Ugly
Unclear architectural patterns
Here’s an example: is it better to handle API requests in your components or in Vuex?
The documentation provides examples on how to handle API logic in Vuex. There is even a nice and colorful diagram:
Does this mean authentication logic goes in Vuex too? Will a state manager start mediating all application logic now?
These are not obvious matters. Most people will simply start sticking non-state logic into Vuex actions or, worse, directly in components because there is a video on Vue’s homepage that says so:
To answer to my initial question: API logic should not be written in Vuex nor in components. There is even a good example on how do that in some of the official code examples.
Conclusion
Vue’s adoption has been growing non stop and I doubt this trend is going to stop anytime soon. It’s still far away from React (at least outside of China) and is constantly competing for a distant second place with Angular.
In the past I’ve argued that Vue is a pragmatic library, unlike React which seems more idealistic (“We are pure JavaScript!”). I still think that’s a good metaphor. On the other hand, I now feel Vue’s anything-goes pragmatism needs a lot more polish, focus, elegance, and simplicity at the user level.
After 2 years my experience with Vue has been positive. I’m still confident it was a good decision to move my team from React to Vue. Not because Vue is better, but because it is a better fit for us.
Vue certainly does the job it’s intended to do, and succeeds in areas that others fail, but today I don’t think Vue is objectively better or worse than the other options likely in your radar.
That is all.
Addendum: Vue CLI
I’ve not included Vue CLI in this article on purpose and I’d like to explain why.
Vue CLI is a very convenient tool for scaffolding Vue projects. In its new imminent version 3 it will be even better, as it’s a complete project management solution.
But, convenience always has a cost and, in my opinion, that cost is not justified here. Webpack is not as difficult as a lot of people claim it is and creating your own starter kit will alleviate most of the configuration time.
Making your own custom tailored thing makes a lot more sense when the cost of doing so is so low.