Background
I would like to share my experience using Vue 2 without a build step in my project and factors using this approach. I started experimenting with Vue.js (Vue 2) back in 2020. One of the nice feature of Vue is the ability to use the framework directly into HTML page without a build tool (compilation). This particular feature is the deciding factor why I selected this framework in migrating a jQuery based web application. I also considered how easy it is to learn and train my team.
The project is a multiple page application (MPA), it consists of a HTML part (UI), an inline Javascript with embedded Vue (UI Handler) and external Vue components.
A Spring boot page controller handles the HTTP requests, webpages generation, session management and connection to the business services. An API controller handles the data flow between the web server to the web browser via REST API.
Frontend Framework Selection Criteria
Features / Capabilities | Vue | React | Angular |
---|---|---|---|
No Build Step | ✅ | ✅ | |
Server Side Rendering | ✅ | ||
Learning curve | ✅ | ✅ | |
Reuse or retrofit existing jQuery components | ✅ | ✅ | ✅ |
No Build Step
The tasks are to upgrade an existing Spring 4 to Spring Boot 2, replace jQuery with Vue, provide bug fixes and add new business functionalities. It is important that we don’t introduce additional build tools into the development process and focus on actual tasks migrating the code and improving the business logic. Angular needed a build step to transpile TypeScript to Javascript while Vue and React can be used without a build step but the latter requires coding in JSX.
The sample code below shows how we use Vue directly with HTML and inline Javascript. Of course, we can also separate the Vue codes into its own dedicate Javascript file.
|
|
Server Side Rendering
The existing spring framework application uses Thymeleaf which is responsible for webpage generation (Server Side Rendering). Using Vue in this scenario is not an issue because it can be embedded directly into HTML pages like a normal Javascript code. We utilized the server side conditional statements to redact or hide pieces of Javascript code inside the generated webpages. The code snippet below shows how Thymeleaf checks if the user has the authority before rendering the specific part of the webpage.
Thymeleaf conditionals inside an inline Javascript
/*[# sec:authorize="hasAnyAuthority('SYSTEM_ADMINISTRATOR', 'OPERATION_ADMINISTRATOR')"]*/
The codes from line 4 to 21 will only be rendered if the user has the required authorization.
|
|
Learning curve
My team and I have experience coding in Javascript, Java and Go. It is only practical to choose a framework where we can reuse existing skill-set. We decided to go with Vue because of its neat coding structure and fantastic attribute, event and input binding.
Class and Style binding
<div class="panel" :class="{ active: isActive, 'text-danger': hasError }"></div>
Event binding
<button @click="viewOrder">View Order</button>
Input binding
<input v-model="order.OrderNumber" placeholder="Order Number" />
Reuse or retrofit existing jQuery components
The project uses a number of jQuery and Javascript components from Telerik and other vendors. Reusing and wrapping them into Vue will save us a lot of time. The existing components were already production tested and the customer don’t want to replace them. Telerik have Vue components, but decided to keep using the existing jQuery based components
Wrapping jQuery component into Vue 2 (prj-datetime-picker.js)
Vue.component('prj-datetime-picker', {
template: `<input :id="id" :value="value" :format="format" />`,
props: {
id: {type: String},
value: {type: String},
format: {type: String},
callback: {type: Function, default: null},
disabled: {
default: false,
}
},
data() {
return {}
},
watch:
{
disabled(v) {
let x = $("#" + this.id).data("kendoDateTimePicker");
x.enable(!v);
},
value: {
handler(v) {
let x = $("#" + this.id).data("kendoDateTimePicker");
if (x !== undefined) {
x.value(v);
}
},
immediate: true,
deep: true,
},
},
methods: {
onChange() {
this.$emit('change', $("#" + this.id).data("kendoDateTimePicker").value());
if (this.callback !== null) {
this.callback(this.id, $("#" + this.id).data("kendoDateTimePicker").value());
}
}
},
mounted() {
$(this.$el).kendoDateTimePicker({
format: this.format,
value: this.value,
change: this.onChange,
});
let x = $("#" + this.id).data("kendoDateTimePicker");
x.enable(!this.disabled);
},
})
We can then use this wrapped jQuery component like a regular Vue component
<prj-datetime-picker id="orderDateTime"
format="dd/MM/yyyy HH:mm" style="width: 100%"
:value="order.startDateTime"
@change="onOrderDateTimeChange">
</prj-datetime-picker>
Conclusion
We completed the project and the customer are very happy with the final software product. It resulted in a more modular code and super easy to maintain, change and extend. Furthermore, we also learned to choose a technology based on existing team skill-set and project timeline, use frameworks or libraries to deliver business solution, reuse or retrofit production tested components, use both modular monolith and microservices to your advantage and to not blindly follow latest technology trends and marketing buzz.