When I joined Optoro, a technology company that helps retailers manage their returns, five years ago, the world of front-end development was in a completely different place. Grunt was the go-to tool, and Gulp was becoming popular. "Bundling" was just concatenating all the JS into a single script.js
. AngularJS was the hottest front-end framework, and CoffeeScript was a socially acceptable language to use.
If you were to time travel from four or five years ago to today, there would be so many new concepts to learn. Changes to ECMAScript alone are huge since five years ago. These things make transitioning from a Gulp + AngularJS to a more modern setup more tricky. On top of that, every developer has their own opinions based on what they've used. Convincing a group of people that X library is better than what they are using takes a lot of effort. Because changing a library/framework isn't as simple as changing your package.json
and a few lines of code. These libraries/frameworks are investments. There is always a cost to adopting a new technology. So balancing costs and benefits of a certain technology is tricky when introducing a technology stack.
Originally we started out with “simple” jQuery user interfaces. As our product grew, we wanted to scale our user interfaces. AngularJS was the best choice for us at the time and we paired it with Grunt to create a mono-repo of AngularJS apps. And with a mono-repo of apps, we needed a build system to build every app. Grunt would help us convert CoffeeScript, SASS, and Haml into JavaScript, CSS, and HTML, respectively. We eventually switched to Gulp for our build system, which lasted us a long time.
But, as you can see from the title of this blog post, we eventually ended up picking Vue over all the other awesome frameworks/libraries out there. Before going into why we picked Vue, I wanted to talk about our steps leading into committing to Vue and adding support for it in our build system. Changing the build system would be required for anything that we would have picked since everything has moved towards modules, bundling and code splitting. We can't get away with the string concatenation of the scripts anymore.
Another convention of the newer frameworks/libraries is using component-based architectures. All of the user interface is built using components. These components are expressed like HTML elements and can be easily reused. Components authors can set specific APIs for their components and allow for more predictable user interfaces. Since we already had a number of applications written in AngularJS, we decided to start by adopting a component-based architecture inside of our current systems. This made developers start planning and architecting their user interfaces with components instead of giant monolithic controllers. As we switched to Vue/React/Angular, we can use that same concept. AngularJS added support for components in version 1.5. This was exciting and refreshing. It really made AngularJS more enjoyable and maintainable. I updated our docs and added support for AngularJS components during our Hack days so our developers can start building components.
While making progress on componentizing our apps, newer frameworks and libraries were becoming more and more popular. Every other day there would be blog posts about React, Vue, or Angular. Internally in our tech department, discussions on what we should use next started coming up. Teams were starting to plan new projects. People felt that it would be a good opportunity to look into alternatives to AngularJS.
As our tech department grew, the difficulty of maintaining our front-end application also grew. With global concatenated scripts, it was becoming really difficult to keep track of things. Since AngularJS automatically injects services into a controller with Dependency Injection, it was often harder to track these services across different modules---the assumption developers made with concatenated scripts was that the injected service was somewhere in the script.js
. It also made it more difficult to debug. Our bundles were pretty big. We were shipping a lot of unused code. It was pretty easy to make AngularJS perform poorly. We eventually added ESLint and John Papa's Angular style guide to improve our code, but that was limited to the JS code. It didn't check the templates, and it was hard to enforce it on existing code bases. The linter eventually was pretty noisy and fixes would take additional time. Overall, we were ready to try something else.
For the successor for AngularJS in our stack, our goal was to pick something developers could adopt quickly and wouldn’t have to go through a huge mental shift. Something familiar would definitely win the hearts of more developers. React was ruled out due to JSX and a complete different way of doing things compared to AngularJS. Angular (2+) was opposed due to being completely different than AngularJS and TypeScript. In the end, Vue seemed like a good alternative to AngularJS. It has similar template syntax and a lot of shared concepts (Directives, Filters, and Components). It’s also easier to learn than React or Angular (2+) coming from AngularJS.
The learning curve wasn't the only part of Vue that attracted us. A lot of our developers found the documentation to be extremely helpful. Everything is organized nicely and the code examples are easy to understand. After reading through the docs extensively, picking up and building something with Vue is relatively easy. Different code samples and examples really cover a lot of ground. I personally benefited a lot from the documentation.
People joke around and say, "There is a new JS framework every five minutes." It's a bit exaggerated and partly correct. If you are not actively following JS Twitter, the rapid pace of development of new tools and technologies can be overwhelming. It's hard to tell if a new library will stick. So far the sticking factor has been the community behind a framework. AngularJS and Ember had set a good example.
Fortunately with Vue we didn't have to worry about that part. The vibrant community around Vue gave us a ton of confidence. It's not Yet Another Framework™. It's being used by a lot of people and it is growing pretty fast. As of December 31st, 2018, Vue has been downloaded 23 million times on npm, vs 1.7 million in 2017, Vue Devtools had about 700k users, vs 84k in 2017, and the Vue Github repository has 130k stars, vs 37k in 2017. Evan You, creator of Vue, mentions a lot of these stats during his State of Vue talks.
By this point we realized that Vue was the perfect candidate for us. After winning the hearts of the people in our Tech Department with Vue, there was still a lot of work before we could deploy Vue code to production.
Now the difficult part is fitting Vue into our build system. I started working on this during our Hack days again. Vue CLI v2 uses webpack and includes different things based on the template. All of our front end apps live in a single git repository and Gulp builds all of them with different plugins, so throwing webpack into the mix was tricky. Eventually, I used one of the best features of npm: npm scripts. By default, Vue CLI adds a handful of npm scripts to develop locally, build for production (minify, uglify, tree-shake, etc.), run tests and lint the JavaScript, CSS, and HTML code. I took advantage of this to have Gulp build Vue apps by calling the correct npm scripts. This way I didn't have to integrate webpack with Gulp. This made a lot of things easier and it will allow us to swap frameworks/libraries easily as long as the correct npm scripts are available. Once I had a working example, I presented it to our developers and everyone was excited.
Months after polishing and fixing bugs in the integration with Vue, we shipped our first Vue app to production on March 2018. Right after that, other teams started building their new apps with Vue and the feedback has been awesome. With the help of Vue's documentation, our developers were able to pick up Vue in a pretty short amount of time. Some of our developers took online courses and some just learned it on the fly. Thanks to code splitting from webpack, our bundles are much smaller and we are lazy loading all of our non-critical code. These performance improvements are going to make the user experience of our applications better by loading faster.
So that's it, right? Have we fixed all of our front end problems by adding Vue and webpack? Of course not. Once we have more teams on Vue, I next want to focus on transitioning the initial webpack setup from Vue CLI v2 to Vue CLI v3. This will allow us to drop all the repetitive webpack configs and have simpler apps.
There is always something to improve and upgrade. This is our first blog post, and we have a lot of awesome posts coming up. I hope you follow us to keep up with what we’re up to! Thank you for reading!
Top comments (13)
This sentence sums up why Vue caught my eye and has become my focus recently. The docs are excellent (and very friendly considering they are technical docs)!
Seems like pretty legit reasons. I know that React has come a long way in terms of ease of use and docs now with most of the 16.x releases behind us. Was wondering if you started a Greenfield project toady.... Do you think you would evaluate again or stick with Vue?
Great article. I truly was trying to find a good situation where someone chose Vue over React or Angular and be able to articulate the reasons well.
It seems you are happy as a team with the decision! And can back up your choice with good reasoning..
Honestly, for greenfield projects we would still stick to Vue. So far it has worked really well for us and there wasn't a situation where Vue was slowing us down or it had us looking for something else.
I am very excited about what's coming up in the next version of Vue.
I've been using Vue for about 3 years and love it. It's simple to learn and the Single File Component system makes understanding the code easy, however, with some of our larger apps, I've started to run into some issues with immutability. Once you start passing around a lot of data, utilizing Vuex and Vue's 2-way data binding becomes increasingly difficult to debug. It's lead to us adding extra boilerplate to ensure we're sending new copies of objects and not mutating existing data and has lended itself to some strange decisions in the code.
Don't get me wrong, I LOVE Vue, but because of these downfalls, I'm considering utilizing React where I wouldn't have before, because of its strong concepts of functional programming/immutability. Sure, we could add things to Vue, like Immutable.js or replace Vuex with Redux, but that adds complexity to the setup that's not well documented, nor is it part of the typical Vue setup.
For now, we're just dealing with any of the issues mentioned when they come up, but I feel like it's making our code less maintainable. It's unclear in the code why some decisions were made unless you run it without the changes. For this reason, I believe in the future we may eventually move to React, unless something changes in Vue 3. As much as I want to stay with Vue, because the ecosystem is wildly easier to learn and operate with, I feel like it's better suited to small-to-medium sized apps than large ones.
I think if you stick to a disciplined approach to data access and mutation, Vue and Vuex scale fine.
I also have rarely used the two way binding in Vue. If you are keeping access to data from store with getters and mutate with actions, things should be easier to scale. Idk how much redux and react will help you if you are following those patterns
You're also going to end up creating a TON of boilerplate code to handle all your mutations. Mapping to Vuex values with one-way :value/@input events, or a get/set computed property is easy if your data is flattened but when you're dealing with large objects and tons of form fields that need to map to nested properties, you end up creating a bunch of actions and mutations to deal with everything. Alternatively, you save your state locally and use v-model to update the fields easily, then you commit to the store on submit. This approach is better with large data sets, so you're not commiting to the store with every field change, but great care has to be taken in order to not mutate the data in the store directly. You must deep clone your objects.
An easier approach with such big objects, is you deepClone them when you're going to edit them.
If the user changes anything, you save the changes; If the user cancels, you destroy the clonedObject.
That way your data remains untouched (whether you brought it from an API, or from Vuex) and you can still submit changes back.
Have you considered nuxt.js instead of Vue CLI?
No. They solve different problems. Plus it's a completely different architecture. We load our Angular.js and Vue apps inside our Rails app.
However, we are considering Nuxt for a future project with a UI outside of our Rails app. I am considering using prerendering as it won't be super dynamic content wise and will be API dependent. That way it will load very fast and can be a PWA as well.
Right. I see. I'm using Nuxt.js in SPA mode (no server side bits) too embed it to some new pages of an existing app. But it's probably won't suit your needs.
I haven't tried the SPA mode in Nuxt yet. I will need to check it out to see the differences between the stuff it outputs vs a Vue CLI project
I was in a very similar situation: I started with AngularJS in 2016, I took a Microsoft Virtual Academy course about MongoDB, Node.js, Express and AngularJS. A year later, a friend of mine recommended me Vue, so I refractored all the app in Vue. I just wanted to learn all the magic under the hood, so I built my components using the Vue CDN. Then, I integrated Gulp and after Vue CLI 3 release, I threw away my Gulp setup.
Today, I am very happy with Vue and I want to integrate TypeScript in my current setup. I am just waiting for Vue 3.0 release 😁
Yeah we had the urge to throw gulp away, but the way we use gulp allows us to not rely on it that much and use any build system we like with it. Gulp just calls npm scripts. Most front end frameworks generate projects with all the npm scripts necessary.
I am also waiting for Vue 3.0 to start using TypeScript as well. I have used Angular a lot. Having a framework written in TS provides an excellent developer experience when using TS.