As a Front End Developer for JFrog, I’ll share some of our journey and challenge which brought us to the new UI on the JFrog Platform UI we recently released.
It was another day at JFrog, back then I was a FED for Xray. My team leader took me aside and told me we were going to do something big. Something which would solve the pain of skipping between tabs, make a common and consistent language between all our products, and help our customers be much more productive.
When we decided to migrate all relevant parts of our products into one platform. We needed to consider the advantages and disadvantages of these two approaches:
The Storming Solution
Allocate a special task force, and replace all components.
Advantage
A dedicated team that will spend a single sprint migrating all components in one effort.
This is a good solution when you have spare people on your team you can allocate exclusively to the mission and will not take part in other roadmap tasks.
When working that way, the dedicated team can plan the start and end of the project more clearly and precisely
Disadvantage
The dedicated team will be blocked for all other tasks while existing products also need development., Also, working on a 5 year old application can lead to unplanned issues during the development process which can block and delay the whole project.
The Hybrid Solution
Create a Vue app which will host the legacy AngularJS application inside. With that, we will be able to have the AngularJS legacy code running inside a Vue component
Advantage
Development time is faster, we can work in parallel with AngularJS and Vue and switch between old screens built in AngularJS to new screens built in Vue. In this way we can be sure all logic still exists and users can still use the functionality while working on the new screen.
Additionally, we can invest more time in planning the new screens when we know there is a solution for the current screen (even though it's written in AngularJS ).
Disadvantage
The main disadvantage is that we carry a lot of redundant legacy code from the AngularJS application just to have the AngularJS app running inside our Vue application. Additionally, it makes debugging more complex since Vue dev tools cannot inspect AngularJS controllers and data flow.
To support AngularJS screens from the legacy applications that hadn’t yet been converted to Vue components, we needed the ability to run AngularJS modules inside a Vue app. We came up with an idea of making an ng-micro-app component to wrap our AngularJS app and provide a communication layer to our Vue app.
Evgeni, our UI Architect, built a nice and easy to work with infrastructure, so the development process was pretty convenient.
We used Vuex as our state manager, and it also acts as our shared data layer so AngularJS can consume the data from the main Vue wrapper (i.e., container) .
The biggest challenge was connecting all the pieces, while keeping data between all application parts synced and flowing smoothly. We wanted users to feel they are working on the same platform, whether they’re using Xray for scanning, Artifactory for deploying, Distribution for releases or... ok, I think you get the idea :)
Strategy
The Bad
While we could immediately dive into the code and start the development process, this is a sure path for bugs and issues we cant expect.
The Good
We decided to mark areas we wanted to start changing. For example, all processes of creating a repository, configuring proxies, and other pages considered low-risk that could achieve a quick win and encourage future migrations.
We held a series of meetings between the UI team leaders, who collaborated on design and allocated tasks to each team..
We used JIRA tickets for each flow with sub-tasks for the required components. This way we could track and see the progress of the flows that were ready for testing and make sure all previous needs and behavior were fully covered.
A new point of Vue
I could dedicate a full blog post explaining why we choose working with Vue, I promise to publish one in the future.
Was it the right decision? It was the right one for us, but for another team React or AngularJS might be the right decision.
One of the reasons we chose Vue was to ease the process for developers who come from the AngularJS world (the majority of us) and also let React developers who join us to feel more comfortable since they are already familiar with the world of UI components and state management so it will be easier for them to adopt.
How can it be achieved
When a route that still uses the AngularJS screen is selected, the correct wrapper will be shown to display the relevant page.
Think of an animal that transforms itself according to a situation.
Our main Vue app component looks like this:
<div>
<ng-micro-app v-show="isNgAppActive"
:active="isNgAppActive"
:state="ngAppState"
@ng-microstatus="onMicroAppStatusUpdate"
@ng-micro-app-state="onMicroAppStateUpdate"
@ng-micro-app-set-event-bus="onMicroAppSetEventBus"
@ng-micro-app-event-bus-dispatch="onMicroAppEventBusDispatch">
</ng-micro-app>
<div v-show="!isNgAppActive" class="vue-app">
<router-view></router-view>
</div>
</div>
The isNgAppActive
flag is changed according to the current route which holds meta information in case its an AngularJS state.
Here’s an example:
// ------------- Application Route ------------- //
{
path: 'path/to/myPage',
name: 'myAwesomePage', <--- the Vue state
meta: {
isNgApp: true, <---- Indicating its an AngularJS route
state: 'MyAwesomeOldPage', <--- the AngularJS state
},
},
{
path: 'path/to/win',
name: 'winningPage', <--- the Vue state
component: WinningComponent, <--- the Component which will be rendered
meta: {
//No Meta Data for this route
},
},
The big picture of our platform should look like this:
Whats Next?
Our roadmap includes completely removing AngularJS from our application and using Vue exclusively. This enables us to remove the complexity and redundant logic of using both, to make debugging much easier and component flow much smoother.
To do so, we need to do it as if petting a hedgehog: slowly and carefully. That means making sure all our unit tests, QA tests, and integration tests pass, so the behavior stays the same and nothing gets broken.
idea of making an ng-micro-app component which will wrap our AngularJS app and will have a communication layer to our Vue app