Why we chose Vue.js over React

Qwintry team recently started active migration to Vue.js as a frontend framework in all our legacy and new projects:

  • in legacy Drupal system (qwintry.com)
  • in our new, completely rewritten qwintry.com branch
  • in Yii2-powered b2b system (logistics.qwintry.com)
  • in all our smaller internal and external projects (mostly with PHP and Node.js backends)

In terms of project size Qwintry is used by around half a million of customers around the world, we run two warehouses (in US and in Germany) on our own software, and we are one of the biggest mailforwarders in United States in terms of visitor and shipment traffic, focusing on Eastern Europe, and Middle East. Basically, we help people to purchase goods in US online stores and manage packages via our control panel when they were received by our warehouse (consolidate/measure/take pictures) and then ship them internationally while saving significantly on shipping costs. We leverage our own IT systems and logistics chains to get the best quality of delivery services for the best price.
Qwintry box
Our package at customer door - from our happy customer reviews

We have pretty big codebase, mostly PHP&JS.

We decided to use Vue.js after we've completed evaluation of modern frameworks: we've built our customer calculator on React, Vue.js and Angular2.

My thoughts on React.js

React skyrocketed the JS world and it is now probably the default choice for JS devs, when we talk about choosing frontend view framework.
I've built some SPAs and dynamic widgets on React, I've played around React Native (under iOS) and Redux as well. I think that React was a great step forward for JS world in terms of state-awareness, and it showed lots of people the real functional programming in a good, practical way. I think React Native is huge - it just changes the landscape of native development.

Cons of React for me are:

Purity, immutability and ideology over getting things done

Don't get me wrong. I appreciate pure functions and simplistic render() approach - no doubt, that's a great idea which is working great in real life. I am talking about other things.
I guess this level of strictness and purity is something that may be useful when you have 1000 devs in your company - just about the time when you decide to develop your own syntax to go for static types in all the PHP code you write. Or when you are a Haskell developer coming to JS world. But most of companies have far smaller dev teams and other goals than Facebook. I will elaborate more on this below.

JSX sucks

I know, I know! It is "just a plain javascript with special syntax". Our design&html guys who need to focus on making this specific form beautiful by wrapping its elements in various quantities of divs - right now - they don't give a sh*t about purity and plain ES6. Applying designs to React components still sucks big time because JSX lacks readability. Not being able to put plain old IF condition to some block of HTML code sucks, please don't believe React fans that keep telling you that you don't need it when you have ternary operators. Let me assure you - this is still a mess of HTML and JS when you edit it and read it, even though it gets compiled to pure JS.

<ul>  
       {items.map(item =>
         <li key={item.id}>{item.name}</li>
       )}
</ul>  

Lots of developers (including me - but I am not there anymore) are thinking that this specific restriction on syntax will make you stronger will help you write more modular code because you have to put your chunks of code to smaller helper functions and use them inside your render() function like this guy suggested:
http://stackoverflow.com/a/38231866/1132016

JSX is also the reason when you have to keep splitting your 15-lines-of-html-code component to 3 components, 5-lines-of-code-in-each.

Don't think that this is a great workaround which makes you a better developer because you now have to structure your code like this.

Here is the thing:
When you write a relatively complex component - which you are probably not going to put to public github repo tomorrow to showcase it on hackernews - this approach of splitting components into super-dumb components because of JSX restrictions will always put you out of flow when you are solving real business task. No, I am not saying that the idea of smaller components is bad or not working.
You should clearly realize that you need to split your code into components to keep you codebase manageable and reusable. But you should do it only when you think that this specific logical entity in your code should be a separate component with own props, - and not on every two-three IFs that you write via ternary operator! Every time you create a new component here and there it costs you and your flow a penny (probably more) because you need to switch from business-task thinking (when you already remember current component state model, and you just need to add some html here and there to make it running) to "manager thinking" - you go create separate file for your component, start thinking about props of this new component, and how they map to state, and how you are going to pass callbacks inside, etc, etc.
As a result you get reduced speed of writing code by being forced to leverage excessive and premature (potential) modularity of components in places where you don't really need it. In my opinion, premature modularity is very similar to premature optimization.

For me and my team the readability of code is important, but it is still very important that writing code is fun. It is not funny to create 6 components when you are implementing really simple calculator widget. In a lot of cases, it is also bad in terms of maintenance, modifications, or applying visual overhaul to some widget, because you need to jump around multiple files/functions and check each small chunk of HTML separately. Again, I am not suggesting to write monoliths - I suggest to use components instead of microcomponents for day-to-day development. It is just about the common sense.

Working with forms and Redux in React will make you type all day long

React is about pureness and clean one way flow, remember? That's why LinkedStateMixin became a persona non grata and now you have to create 10 functions to get input from 10 inputs. 80% of these functions will contain single line with this.setState() call, or redux action call (then you will probably have to create another 10 constants - one per each input). I guess that would be acceptable if you could generate all this code by thinking about it.. but I am not aware of any IDE that could significantly improve this.
Why do you have to type so much? Because two-way binding is considered dangerous by big guys in big-enterprise apps. I can confirm that two-way data flow code sometimes is not as clean to read, but most of these fears are mixed with overall pain about Angular 1 where two-way binding was bad, and still.. probably it was not the biggest fail even there.

Let me show you the quick-editor set of components I've built recently with Vue.js for our Drupal website (I beg your pardon for the design - it is a backend UI for our operators, and our designers are busy creating frontend interfaces for our customers so this piece is waiting to get design overhaul):

I can't share the code for obvious reasons but writing it in Vue was real fun, and the code is very readable.

And I know for sure that creating a separate function for each input to handle a widget like this in React would certainly not make me happy.

Redux sounds like a synonym of verbosity, as well. And it's easy to find developers that blame that Mobx is turning React into Angular just because because it leverages two-way binding - see my point #1 about purity. It looks like a lot of smart people value purity of their codebase more than getting job done (which is fine if you don't have deadlines, I guess).

Excessive tooling

React was created with Babel in mind. You can't do a step in real-world React app without a bunch of npm packages here, compiler to ES5 going first. Simple app based on official react starting package code has around 75MB of JS code in node_modules.
It is not a critical thing, it's more related to JS world in overall than to React, but it adds up to overall frustration when using React as well.

Angular 1: too much freedom is sometimes bad

Angular 1 was a great frontend framework that is located in the opposite corner (from React) of the imaginary JS map of purity and readability of codebases - it allows you to start quickly, it gives you some real fun for your first 1k lines of code, and then it practically forces you to write shitty code. You will probably get lost in directives, scopes, and two way data flows across all the layers of your app will just be a cherry on the pie of the code that your freshly hired devs won't even want to touch because it won't be manageable.

Why so?
Angular.js was created in 2009 when frontend world looked pretty simple and nobody was even thinking about state hygiene. You can't blame these guys - they were just creating competitor of Backbone with some new concepts and they wanted to do less typing.

Angular2

Just build hello world app and look at the amount of files you got in your repo. You will have to use Typescript (and I am not 100% sure it is something I am going to enjoy doing every day - great writeup from Eric Eliott on this topic) and compilers to start working. It was enough for me.. For me is still too much typing before I start real work. To my mind, Angular 2 guys are trying to build perfect framework which will beat React, instead of trying to build a framework which solves business tasks for average user. May be I am wrong and my mind might change - I don't have a lot of experience building Angular2 apps yet, we've just built demo customer calculator app for our in-house evaluation. Wonderful comparison page on Vue.js website states that Angular2 is a good framework which share a lot of concepts with Vue.

Vue.js

In short, Vue.js is a thing that I've been waiting for a long time ( I will be talking about Vue.js 2 which got quite a few improvements over first version of Vue and this is the current stable framework version). For me, in terms of elegance and conciseness, and focus on getting things done, Vue.js is the biggest change to JS after the day when I was blown out by jQuery in 2007.
If you look to Vue.js popularity graphs you will notice it is not just me: https://www.google.ru/trends/explore?q=vue.js,react.js,angular.js
Vue.js is one of the most rapidly growing JS frameworks in 2016, and I think it's not just another hype based on fans that switch to newer JS framework every 3 months, or authority (and money) of one big company.

Laravel added Vue.js to core, which is a big thing.

Pros of Vue.js

Vue.js hits a sweet spot between readability&maintainability and fun. A spot between React and Angular 1, and if you look at Vue guideline, you will instantly notice how many nice things it got from these frameworks.
From React, it got component-based approach, props, one-way data flow for components hierarchy, performance, virtual rendering ability, and understanding of importance of proper state management of apps.
From Angular, it got similar templates with good syntax, and two-way binding when you need it (inside single component).

Vue.js is very easy to start - I've seen this in our team. It does not enforce any compilers by default, so it's really easy to drop in Vue to your legacy codebase and start improving your jQuery mess with good JS code.

Right amount of Magic

Vue.js is very easy to work with, both in HTML and JS - you can do pretty complex templates without losing your focus on business task and the template usually maintains great readability even when it gets really big - at this moment you've usually made a good progress in terms of business task solved, and you might want to refactor templates and split them into smaller components - at this moment you see the whole "picture" of your app a lot better than at the moment when you've started.

From my experience, this differs vastly from approach that I used to have in React: I saved myself a lot of hours here. In React, you have to split components into micro-components and micro-functions at the time of writing the initial version of your code - or you will literally get buried in the mess of your code. In React you will spend a lot of time polishing the props and refactoring your super-small components (that will never be re-used later) again and again since you don't see clearly if you have to change the flow of your app logic somewhere in the middle of the code writing process.

Working with html forms is a breeze in Vue. This is where two-way binding shines. It does not bring any issues to me even in complex cases, though watchers may remind of Angular 1 at first glance. One-way flow with callback passing is always at your service when you do your components splitting.

If you want some compiler magic, linting, PostCSS and ES6 - you got it. Vue extension seems to become a default way of writing public components in Vue.js 2. By the way, idea of scoped CSS of component, working out of the box, is something that looks really nice and can reduce need in proper css hierarchy naming and technologies like BEM.

Vue.js has pretty simple and useful state and props management in core, via data() and props() methods - they work great in real world. Better separation of concerns available via Vuex (which is to my understanding similar to Mobx in React - with some mutation of state involved).

I think a good percent of Vue.js use cases won't ever require such a state management as Vuex provides, but it is always good to have an option.

Cons of VueJS

  1. The biggest one: not descriptive runtime errors in templates. This is pretty similar to Angular 1. Vue.js manages to give a lot of useful warnings for your JS code, for example there are warnings when you try to mutate props, or using data() method incorrectly - the good influence of React can be very well seen here. But runtime errors in templates are still a weak point of Vue - exception stacktraces in a lot of times are not useful and are leading into Vue.js internal methods.
  2. The framework is young. No stable community components - a lot of them were built for Vue.js 1, and it is sometimes not easy for newcomers to see from github repo which version of Vue the library is built for. This issue is leveled by the fact that you can do huge things in Vue without any additional libraries - you will probably just need some ajax library (vue-resource will be a good choice if you don't care about isomorphic apps, axios otherwise), and probably vue-router which is considered as core library with good support.
  3. Chinese comments in code across most of community libraries - this is not surprising, Vue.js is getting very popular in China (the author speaks Chinese).
  4. Single-guy project? Not exactly a real issue, but something to consider. Evan You is the guy who built Vue, after working at Google and Meteor. Laravel also used to be a single-guy project, it is still a huge success, but you never know..

Vue.js in Drupal

Disclaimer: we do not plan to use Drupal 8 any time soon at Qwintry, since we are switching to faster and simpler PHP&Node.js frameworks, and our legacy codebase is Drupal 7.
Since our legacy system qwintry.com is powered by Drupal, it was very important for us to test this new framework here, in the wild. I am not proud by a lot of code in our legacy codebase, but it works and generates our revenue, so we respect it, improve it, and build a lot of new features here. Here are the list of things I've built in Vue&Drupal already:
In-place node editing for complex order entities. This includes generating invoices for customers, and quick edit of product items. It required building basic JSON api for loading and saving of nodes - nothing too fancy, just a few menu callbacks.
Two REST-powered dashboards for proprietary Saas software we are using so our customer support does not have to login to separate websites to quickly check information related to specific customer - everything is built right inside customer profile in our website now.

I know a lot of backend developers are still stuck in 2010 and Drupal 7 core Ajax system.
I know how complex Drupal might be when you try to build some fancy multi-step ajax interaction form using core features - it's just crazy hard to maintain this code later. Yes, I am looking at you, ctools_wizard_multistep_form() and you, ajax_render!
At the same time, these Drupal developers are pushed forward by modern world UI requirements, but they might be scared by increased complexity of modern JS frameworks. Yep, it's me a year ago. Let me tell you - you won't find a better time and way to improve your interfaces than get Vue.js now, put it in your /sites/all/libraries, add it via drupal_add_js() to your template, and start hacking around. You will be shocked how easier it is to maintain a number of pure JSON callbacks sitting in your hook_menu when the client side, including forms, is completely powered by Vue.

Vue.js in Yii2

Fun fact: Yii was created by a Chinese speaking guy - Qiang Xue. So, you might call Yii+Vue stack not just very difficult to pronounce, but also a Chinese stack :)
For our new version of Qwintry.com (not yet public) we chose Yii2 which I believe is one of the best and fastest PHP frameworks available. It is definitely not as popular as Laravel which is rocking the PHP world now, but we are pretty happy with our Yii2 stack now (though we are looking at Laravel from time to time, the guys are doing a great job).
We are gradually reducing amount of html generated by Yii2 and PHP, and concentrating more on REST backend which generates JSON for our client-side which is powered by Vue.js. It is mostly API-first approach for all our Active Record models.
Here, we are taking API seriously and that's why we are spending a lot of time building good API documentation even though it is only used in-house.
With PHP7&latest MySQL the response times of our Yii2 JSON backend does not differ much from Node.js backends (15-20ms are the numbers I am talking about), so it's more than enough for our needs, and 10-20 times faster than we could imagine to achieve using Drupal. At the same time, it's good&old PHP with all the power of composer libraries and stable codebase at our hands.
So, Yii2&Vue.js responsiveness is huge, and in terms of code it's a pleasure to work with.

We are also using Vue.js in a number of internal projects.

Conclusion

We've been writing Vue.js code every day for around 3 months in various projects, with impressive results. 3 months is nothing in backend world, but it is something in JS world :) We'll see how it goes further.

I expect Vue to become a primary JS framework in 16-24 months if Evan You makes right steps, at least around backenders and smaller teams of frontenders. I still consider React stack to be the primary JS framework of 2017, especially if React Native manages to mature and improve itself with same pace it used to.

UPD: this post got to frontpage of HackerNews and there is useful discussion with 200+ comments there: https://news.ycombinator.com/item?id=13151317
It also got to top posts of Reddit webdev, 70+ comments here: https://www.reddit.com/r/webdev/comments/5ho71i/why_we_chose_vuejs_over_react/

Anton Sidashin

I am a web developer and CTO with 15+ years of experience, and I am passionate about performance, usability, and getting things done.

Samara, Russia