Refactor legacy code, Vue that was easy!

VueDay

Verona

12/04/2019

Nicolò (Nico) Maria Mezzopera

@DonNicoJs

Who am I

Nicolò (Nico) Maria Mezzopera

  • Senior Frontend Developer @ Pulilab

  • More than 8 years of experience

  • Vue2Leaflet maintainer

  • vue-xlsx author

TLDR

  • Refactor legacy code is not always an impossible task
  • Migrating your codebase to Vue can be approached in many ways
  • Having Vue and another framework coexist is not a nightmare
  • We can rely on established and well known patterns

Manager / PM / PO:

We are here to go from eww to:

Strategies

  • One Vue per day

  • VueOrchestrator

One Vue per day

  • Identify new 'standalone' features
  • Leverage Vue small footprint to create web components
  • Use the web components until the time is ripe to rewrite the section/page in Vue

The VueOrchestrator

  • Rewrite routing in vue-router
  • Rewrite data storage in Vuex (optional)
  • Use the clear hooks coming from vue-router/vue lifecylce to mount the previous codebase components and feed them data via Vuex

One Vue per day

  • Floating elements
  • Shared complex UI components
  • Modals

Perfect use cases:

...keeps the refactor away

One Vue per day

  • Limited time to allocate to refactor
  • Few / one developer involved
  • Is easy to keep the UI homogenous without third party libraries

When

One Vue per day

  • Spin up a new VueJs codebase
  • Create your reusable components
  • Compile them as WebComponents
  • Deploy them to npm or similar registry
  • Consume your web components in your main codebase

How

One Vue per day

  • Web components require polyfills on older browsers
  • Limitation due to shadow dom issue on styling
  • Split codebase
  • They are not a solution to our problem but a very good starting point

Cons

One Vue per day

Example: Contact me Dot

One Vue per day

 Why: Contact me Dot

  • Standalone functionality

  • Reusable across different web apps

  • Show off 'VueJs'

One Vue per day

 Internals: Contact me Dot

One Vue per day

 Integration: Contact me Dot

<script src="//unpkg.com/vue-django-feedback/dist/packaged/vue-django-feedback.js"></script>
<vue-django-feedback
  meta="{{vm.meta}}"
  name="{{vm.user.profile.name}}"
  email="{{vm.user.profile.email}}"
  auth-token="{{vm.token}}"
  submit-button-text="{{'SUBMIT' | translate }}"
  global-error-warning="{{'ERROR' | translate }}"
  name-label="{{'Your name' | translate }}"
  email-label="{{'Your email' | translate }}"
  subject-label="{{'Subject' | translate }}"
  message-label="{{'Message / Question' | translate }}"
>
  <span vue-slot="header-text">
    <translate>
        Ask our experts!
    </translate>
  </span>

</vue-django-feedback>

One Vue per day

One Vue per day

Why was it a success? 

  • It was the precursor of a bigger refactor
  • Even if it was in the codebase being refactored we still use the original code
  • Developing it in Vue was faster than doing it in AngularJs

VueOrchestrator

  • Major refactor needed
  • Totally new pages need to be added
  • Lots of ready and battle-proven UI components

Perfect use cases:

VueOrchestrator

  • The codebase does not follow any standardised/opinionated approach
  • Frequent bug due to async issues/callback hell
  • A bigger chunk of time can be allocated to the refactor

When

VueOrchestrator

  • Spin up a new codebase based on VueCli / Nuxt
  • Rewrite all the routes in vue-router
  • Optionally rewrite/create state manager in Vuex
  • Create wrapping components
  • Import old code in each page

How

VueOrchestrator

  • A good amount of time is needed for this approach
  • Results may not be 'immediately' visible
  • Vuex state management may be a bit quirky to adapt to older code 'style'

Cons

VueOrchestrator

Case Study: DigitalHealthAtlas

VueOrchestrator

Why: DigitalHealthAtlas

  • The project started years ago as an AngularJs website
  • As the software kept evolving refactor came as a necessity
  • When a big piece of the software was added we managed to refactor huge chunks to Vue with a minimal overhead

VueOrchestrator

Internals: DigitalHealthAtlas

  • Nuxt Js in Universal mode
  • AngularJs / Vue Integration
  • Vuex as a global state manager
  • 150+ components 
  • 10+ store modules
  • ~100k lines of code (JS / JSON / VUE)

VueOrchestrator

Integration: DigitalHealthAtlas

Legacy component in SSR Page:

 

<template>
  <div class="angularjs">
    <div id="thematicjs" />
    <!-- placeholder to avoid a flash of content -->
    <a
      v-if="!initialised"
      class="HeaderBtn ToolkitBtn"
    >
      <translate>Toolkit</translate>
    </a>
  </div>
</template>
<script>
export default {
  data () {
    return {
      initialised: false
    };
  },
  async mounted () {
    await this.$nextTick();
    const { factory } = await import('@/angular/Thematic/thematicFactory');
    factory(0, 0, this.$gettext('MAPS Toolkit'), 'HeaderBtn', this.$gettext('Toolkit'));
    this.initialised = true;
  }
};
</script>

VueOrchestrator

Integration: DigitalHealthAtlas

AngularJs Page

<template>
  <div class="angularjs">
    <div id="cmsjs" />
  </div>
</template>

<script>

export default {
  async mounted () {
    const { cmsFactory } = await import('@/angular/Cms/cmsFactory');
    cmsFactory();
  }
};
</script>

VueOrchestrator

Why was it a success

  • Got rid of a huge piece of legacy code
  • Completed a refactor in the timeframe of developing a new feature
  • Better understood why VueJs architecture is amazing for integration with other frameworks

Legacy code as Vue component

  • Mounted hook: the holy grail
  • Placeholder DOM elements
  • SSR compatibility

Key parts:

Legacy code as Vue component

Let's check the code: https://codesandbox.io/s/j3246j07kw

Legacy page as Vue component

  • Factory function to bootstrap legacy code (AngularJs)
  • Dom placeholder element
  • Appropriate loaders
  • A bit of DOM manipulation

Key parts:

Legacy page as vue component

Special thanks to
my Wife and this wonderful fellas:

Walter Tommasi

@walter_tommasi

Dobromir Hristov

@d_m_hristov

András Takács

@paragonhex

Find me at

DonNicoJs

@DonNicoJs

donnico

DonNico

Thank you!

Made with Slides.com