From KnockoutJS to VUE

How we planned the transition of our biggest frontend project from a “legacy” framework to a modern one

Paolo Marchezzolo
THRON tech blog
6 min readJun 19, 2019

--

Our main product web interface has been developed since 2010 and served us well for a long time. Over the years our product grew in its size, browser technologies massively evolved and our technology stack became a limit (both for maintenance and production perspectives). We had to face the task of refactoring all our legacy code into smaller components, a modern frontend stack and improving our productivity.

Migrating from an “older”, aging frontend technology stack to a modern, “shiny” one is a consideration and a dilemma that almost every frontend developer faces at least once in its career. We recently tackled this problem and decided to start to phase out KnockoutJS from our web application. In this article we will try to outline why such a transition was deemed necessary, and how we picked from the wide pool of available frameworks.

Why migrate?

KnockoutJS is an excellent library; however, if the application is big/complex enough, it shows some limitations:

  • it’s a library, not a framework: it’s designed to handle data-binding, and little else, leaving the task to find suitable libraries or tools to handle many other things (internationalisation, component lifecycle hooks, network requests, state management);
  • performance: modern frameworks leverage new language/browser features not available with KnockoutJS; this shows especially in long/nested lists with components, where KnockoutJS can quickly become unbearably slow, in our experience;
  • community support and development: KnockoutJS is a stable framework, which is good, but has the downside that many of its limitations won’t be resolved quickly (if at all); also, the community interest for it is waning, and it’s much easier to find resources (articles, libraries/plugins, tools) for new frameworks instead.

KnockoutJS is far from dead, and it’s actually still being improved and evolved (see Technical Knockout) but newer frameworks seem a far better bet for our needs, considering activity and performance.

Selection criteria (requirements)

Picking a technology usually involves a series of trade-offs; we asked ourselves which aspects of a new framework are more valuable to us and which are just nice bonuses that can be overlooked, if necessary. We analysed the following points:

  • accessible learning curve: this is a critical aspect since it both allows us to focus on business logic instead of cumbersome technicalities and also allows new hires or new members of any project to be brought to speed more easily;
  • interoperability: we need to be able to integrate the new framework in various situations (inside customer websites, as standalone product, or inside browser extensions/mobile apps), so we need the framework to support several different scenarios;
  • community and support: an active community is a requirement for a healthy and evolving framework ecosystem, it reduces the chance to be forced to change technology stack in just a couple of years;
  • stick to standard languages: we want to keep additional languages and tools to the minimum, sticking with standard ES6+; this makes easier for us to re-use old code (which would be hard, for example, with Typescript) and to migrate to a new framework when necessary down the road.

Selecting candidates

The JS ecosystem is incredibly rich in libraries, frameworks and even languages that compile to it, so we needed to filter potential choices without “trying them all”. Luckily, our requirements are helpful in doing so. We are looking for ease of adoption and interoperability, so things like Elm or Svelte do not fit the requirements. Also, libraries like Inferno are very interesting, but they are not ideal for our use case since their community is too small, and the risk of them disappearing or their development being dropped is significant. After those considerations (and after pruning our “older” alternatives like Ember and Backbone, that didn’t make much sense with a modernisation goal) we are left with the “big three” JS libraries/frameworks, which have been evaluated more in-depth.

Angular

Angular is a full-featured framework that aims to provide the developer with everything needed for development of a modern web application (network requests, state management, toolchain, testing). Its opinionated approach means it is easier (although sometimes limiting) to identify the “Angular way” to do something, which gives you a clear way to code and organise your project. It features Typescript to enforce static typing, type-checking and inference.

While the multiple features and tools Angular brings to the table are interesting, its “monolithic approach” worried us, both from a performance and complexity standpoint. Since everything is already included, projects that already use other libraries may run the risk of including duplicate functionality (and incur in increased complexity).

React

React is much more lightweight and slim than Angular; it is a library, not a framework, and it defers to third-parties things like routing, state management, and network requests. This causes an abundance of options, however it also burdens the developer with finding and integrating the “right” plugin/library for many things, we would prefer a more streamlined solution. It is also the hardest to learn because of its functional programming approach and the use of JSX instead of plain old HTML. It is also worth mentioning that during our evaluation period React was also scope of a licensing FUD (fear uncertainty and doubt).

Vue

Vue.js is an intermediate approach between the “batteries included” Angular provides and the minimal one of React. It has “official” libraries for routing and state management (although optional — they are not in the core, but they are managed from the core Vue team, so they are guaranteed to work well with it). Also, it is designed to be “incrementally adoptable”, which looks good for our interoperability needs, and it is easier to learn in comparison with Angular and React.

The choice

As you may have already guessed, we ended up picking Vue.js, since its strong points better align with our requirements, and its downsides aren’t too relevant for us. Out evaluation of Vue.js in summary:

  • greater performance than KnockoutJS (moot point in comparison — React and Angular are also good here);
  • it is designed to be integrated in other implementations and adopted gradually;
  • it has the best learning curve compared to the benefits it brings in;
  • while the community is smaller than React’s and Angular’s, it is the fastest growing one, which makes us less worried about it being abandoned or starved for library/plugin options.

After a brief scouting, we initially adopted Vue in a small project that we integrated in our main application afterwards. It was (mostly) painless, and it convinced us it was time to start using it at scale and start migrating parts of legacy code towards it. Nowadays, we are re-engineering the core parts of our application to support both technologies, which is needed to enable a full but gradual rewrite in Vue and the complete removal of Knockout.

After few months from the adoption

Vue proved to be a pleasure to work with: it “forces” you to write and organise your code clearly, it’s very approachable and integrates well with our existing codebase(s). We liked a lot the “single file component” approach that lets us keep our code as compact as possible without spreading it between CSS, JS and HTML files.

The aspects that troubled us the most are tooling-related: since single file components require you to write .vue files instead of “standard” .js, we had a hard time setting up the customisations with eslint, babel, various documentation and automation tools. Community-provided options revealed to be not good enough and we have been forced to roll our own solution more often than we had predicted. An example is the approach we are using for documentation: things like Vue Styleguidist are great but too limiting—we are now testing a hybrid solution based on JSDoc (documentation.js) for parsing and Vuepress to produce actual documentation in a beautiful and customisable way.

This is probably the point worth expanding more in the future: we need to better understand and integrate tools specifically designed for Vue. Ideally we want to build a technology stack that is complete enough to support all our current needs, but also simple enough that starting a new (small or big) project is painless and approachable to someone that has little experience with it.

Regardless of those “issues”, we are very satisfied with our choice. We look forward to learning and enjoying more and more working with Vue.

--

--