Over a million developers have joined DZone.
{{announcement.body}}
{{announcement.title}}

How and Why We Moved to Vue.js

DZone 's Guide to

How and Why We Moved to Vue.js

A developer discusses why his team moved to Vue.js for their front-end efforts, the effects it had on their code, and more.

· Web Dev Zone ·
Free Resource

Disclaimer: In this article, a dev one who can’t stand the front-end and doesn’t know how to work with it writes about working with it, choosing a JavaScript framework, and why Vue.js is a great choice. You’ve been warned.

I’m very bad with the front-end and don’t like it. The rest of our team has the same feelings. We prefer to focus on the backend and either outsource the front-end or go through the trial of doing it ourselves, often having to rework it again and again.

In early 2017, we almost solved the problem with the front-end, as we hired an expert who made the whole site over using BEM, proper grid, etc. It’s nearly impossible to start using BEM for a three-year old project in a single sitting. We’re still working on that and when we’re done, we’ll tell about the result here.

But when it came to problems with our JavaScript code, we didn’t even try to solve them. Mkdev is not a single-page application; we don’t have a huge pile of interactive elements and complex visual editors. In some places we use a datepicker, in some there’s a drag-and-drop technology to sort, for the articles we use the simplest Markdown. Everything is so boring, that we have used ready-made jQuery plug-ins for three years and haven’t given a damn about the rest. Until recently.

99 Mistakes One Can Make While Writing the Code Using jQuery

We have a payment form which can be seen in the profile of any mentor. There’s a slider to choose the amount of weeks in the form. The buttons are dynamically updated according to the slider. Take a break from reading and play around with this slider to see what we’re talking about.

Did you? Do you see now how the form is updated according to the slider and the buttons and how the price is dynamically changed on the button? Well, over the years the front-end code of this form transformed into the most horrible thing the one can do with jQuery.

Let’s have a look at some of the examples of this horror.

Far Too Many Conditional Statements

if (window.location.pathname == "/dashboard/account") {
  $("#button-payment-block, .link-cancel").hide();
} else {
  $("#payment-block, #mentor-payment__login-form-container").hide();
  var value = $("#button-payment-block").text().split(" ").splice(0,3).join(" ");
  $("#button-payment-block").html(value);
}

Hideous String Parsing

if ( $('.payment-form__weekly-price').html() ) {
  var arr = $(".payment-form__weekly-price").html().split(" ");
  var current_price_for_week = (options.total / (number_of_days / 7)).toFixed(1);
  arr.splice(3, 1, 'ˆ' + current_price_for_week);
  $('.payment-form__weekly-price').html(arr.join(" "));
}

Constant Operations With the DOM

$cardForm.show();
$cardForm.find('input[type=submit]').prop("disabled", false);
$('.upgrade-block .upgrade__payment-block, .upgrade-block .upgrade__title, .upgrade-block .upgrade__info').hide();
$('#upgrade__payment-block--payment-button').hide();
$('.upgrade-block').css({'border': 'none'});

There are 284 lines of this kind of unbearable mess, which is absolutely impossible for anybody to grasp. The added complication is that element IDs are not even close to the point of this element: #upgrade__payment-block--payment-button might turn up to be a button to upgrade the subscrption or just a payment button. So go figure.

Hopefully, dear reader, this has given you an idea about how crazy the disaster is.

Which JavaScript Framework to Choose?

We were considering two options:

  1. Rewriting all the code from scratch, using the same technologies, but doing it properly this time.
  2. Choosing any library which would allow us to write good code out-of-the-box.

We were afraid that if we chose the first option, in a year we wouldn’t be able to understand our own code again. So we chose the second one. We needed a library or a framework, which:

  1. Could be implemented iteratively, only for the smallest parts of the front-end.
  2. Being out-of-the-box, would be powerful enough to solve all our problems without further ado.
  3. Would be simple enough to grasp it decently for a couple of weekend hours.

We chose Vue right away and without any second thought. Frankly speaking, the choice was made right after we read Ivan Shamatov’s wonderful article, Rails 5 and Vue.js: how to stop worrying and love the front-end. Looking through the documentation for Vue.js, I decided to give it a shot.

Webpacker, PostCSS, Babel, Yarn... Go Away

Taking Ivan Shamatov’s advice into account, I ran a Rails generator for all the trendy front-end things, hoping to implement Webpack really quickly. Unfortunately, it also generated Babel and PostCSS on top of that, which I didn’t plan to generate at all. Moreover, it turned out that I had to use Yarn now. At this stage, I ran out of my patience so I just eliminated all the junk generated by Rails.

Stop saying that, Kirill! It’s not junk, these are the most important tools of the modern front-end development!!

Yean, I agree. I guess the time for ‘modern’ front-end development for mkdev code hasn’t come yet. The standard assets pipeline works fine for us, as well as loading the third-party JS libraries through Gems or adding vendor/assets. We hate implementing dozens of new technologies just because it’s cool and trendy.

I took vuejs-rails and added another couple of libraries (e.g. for the slider) directly to vendor/assets. This approach has its own disadvantages for sure, but they are not really significant at this time.

Falling in Love With Vue.js

I’m not going to teach you how to use Vue.js – it has superior documentation. But if you want to master it (especially combined with Ruby on Rails), you should hire Ivan Shamatov as your mentor. So, in the rest of the article, you’ll see how we implemented Vue.js to mkdev.me, as well as our experiences with and feelings about Vue.

Learning Curve of Vue.js

Having spent about 6-7 hours in total on Vue.js, I managed to completely rewrite the whole front-end part of our payment form using Vue.js and to send it to production. Not so shabby, keeping in mind that the technology is absolutely new to me.

Code in Vue.js Is by Far Shorter and Clearer

If we estimate the amount of code, we’ll see that the payments.js file has been cut to 166 lines. More than 30 of them are used for the slider component appearance. The component is nice, but it forces us to describe its appearance right in the JS code for some unknown reason.

This Vue.js component just defines its properties and methods. Without any unnecessary details, here’s how our payment form looks right now:

 Vue.component('payment-form', {
      template: '#payment-form-template',
      props: [
        'initial_upgrade',
        'mentor_id',
        'initial_number_of_weeks',
        'current_user_is_present',
        'has_mentor'
      ],
      data: function() {
        return {
          coupon: "",
          error_message: "",
          final_form_visible: this.mentor_id == null, // Either login or card details form
          loading: false,
          number_of_weeks: this.initial_number_of_weeks,
          price: 0,
          upgrade: this.initial_upgrade,
          upgrade_notice_visible: this.initial_upgrade,
          weekly_price: 0,
          card: {
            // ...
          },
          slider: {
            // ...
          }
        }
      },
      components: {
        'vueSlider': window['vue-slider-component'],
        'vueMaskedInput': window['VueTheMask']
      },
      computed: {
        can_proceed_to_final_form: function() {
          return !(this.number_of_weeks == 0 || (this.has_mentor && this.mentor_id != null));
        }
      },
      watch: {
        number_of_weeks: function(val) { this.setPrice(); },
        coupon: function(val) { this.setPrice(); },
        price: function(val) {
          this.weekly_price = (this.price / this.number_of_weeks).toFixed(1);
        }
      },
      methods: {
        setPrice: function() {
          // ...
        },
        getStripeToken: function(event) {
          // ...
        },
        showFinalForm: function(event) {
          // ...
        },
        toggleViews: function(event) {
          // ...
        }
      },
      created: function () {
        this.setPrice();
      }
    })

In the template, we indicate where to output these properties and which method to request with which action. For example:

<a href="#"
   class="payment__button button button--centered"
   v-bind:class="[can_proceed_to_final_form ? '' : 'button--disabled']"
   v-if="!final_form_visible"
   v-on:click.prevent="showFinalForm">
  <%= t ".enroll_for", price: "{{price}}" %>
</a>
<! --- >
<template v-if="final_form_visible">
  <p class="payment__notice payment__notice--centered">
    <%= raw t '.to_continue' %>
  </p>
  <%= render "login_form" %>
  <%= link_to t('.cancel'), "#",
              class: "payment__cancel-link",
              "v-if" => "final_form_visible",
              "v-on:click.prevent" => "final_form_visible = false" %>
</template>

The elements hide by themselves and are shown according to the component properties and binding events to the elements (clicking the button) is occuring right in the template.

It’s Not So Convenient to Reference the Components Without the Webpacker, but it’s Not a Big Deal

Ideally, Vue.js components are each stored in a separate Vue file. The template, code, and even CSS are also stored there. Leaving the Webpacker behind, we (presumably) have lost an ability to do so. Luckily, Vue.js offers some alternative ways to define the component. X-Templates way suited us and our system with the assets pipeline perfectly:

<script type="text/x-template" id="payment-form-template">
  <div class="payment"
       v-bind:class="[upgrade_notice_visible ? 'payment--large' : '']">
<! -- >
</script>

Vue.js Is Very Handy to Incorporate Part by Part

I’ve already mentioned it a little, but I’d better note it once again: Vue.js doesn’t make you rewrite all your code. We took just one component, a payment form, and used Vue.js. The rest remained unchanged.

There Are Millions of Plug-ins for Vue.js

I was afraid I wouldn't find the same amount of ready-made solutions for Vue.js as I had for jQuery. It turned out that there were a lot of components for the slider and for the masked input. Having searched the Internet, I also found the components for the datepicker, for the tables, and a lot more.

Better Tomorrow for the mkdev.me Front-End

Let’s sum it up.

I managed to rewrite the most complicated front-end component of our project using Vue.js in no time. As a result, the code got simpler, cleaner, and more supportable. Vue.js is a great, simple, and fast tool, which doesn’t make you to learn new architecture. The experience is the same as it was with jQuery: you just code following the simplest rules and it goes pretty well.

Sure enough, over time, jQuery shoots you in the feet, and maybe Vue.js will, too. But for now it successfully healed the wounds inflicted by its predecessor.

Of course, we haven’t mastered Vue.js yet. We have also planned a couple dozen minor fixes and improvements for our payment form code. Then we’re going to get rid of jQuery step by step and move to Vue.js components completely. Maybe we will even implement Webpack in the end.

Another bonus from Vue.js is that our mkdev developers are interested in examining it, working with it, and implementing it. And this is a new page in mkdev's front-end development efforts.

Topics:
vuejs ,web dev ,front-end development ,vue.js tutorial

Published at DZone with permission of

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}