From Broad Strokes To Balanced Screens — Building the Front End

Leveraging Vue.js and Vuetify to transform a wireframe 🎨 into a full-featured front end 🖥 rapidly and efficiently 🚀.

Goetz Buerkle
UnscrewMe

--

(This article has been featured in the Official Vue News #90.)

(First proper design idea drawn up on my iPad on holiday at Het Groene Paleis in Amsterdam.)

After picking a front end framework, learning the basics about Vue.js and getting the first front end experiments online, we ran out of excuses not to work on the actual user interface. The next goal for UnscrewMe was pretty clear at this stage: build something that looks okay, and works basically like the final product should work – yet still missing a couple of features.

Getting used to the new syntax and concepts took a while. Having realised that keeping too closely to the “Material Design” guidelines did not really align well with the product we envisioned, we began taking a more liberal approach. Thanks to my previous experience with Bootstrap, I could build a basic layout in Vuetify quite easily (see also Vuetify on Medium).

Exploring different programming paradigms

An early challenge was to wrap my head around modern JavaScript language features like “Promises” in combination with asynchronous code execution. Coming from Python and Django, most recently, I had not had much – or actually any – exposure to asynchronous code execution.

I needed to read a couple of basic articles to build an understanding of the concepts that Vue.js (see also The Vue Point on Medium) and other libraries like axios relied on. To avoid subtle errors, that might not always be too obvious, it was important to comprehend the implications on code execution time and sequence.

Overcoming caching challenges

As I have decided not to set up Webpack so far, I also cannot benefit from cool features like hot code reload. Not a big problem, but this means that I am constantly reloading pages in my browser.

At one point, I wondered why some changes I had made in the code did not have any effect, even after repeatedly reloading, with Chrome Developer Tools open. I added some debug console output and finally realised, that my new code might be fine, but it didn’t even get loaded at all. Soon enough, I eventually figured out that Chrome caching can be easily turned off in the developer tools and it will remain off while the Developer Tools are open, but this was too late for me – I had already used this delay as a reason to check out the then newly released Firefox Quantum. In Firefox Quantum things worked as expected, so I could do a deployment and make some progress on my user interface.

Uncovering unexpected pitfalls

Overall, I very much enjoy the level of abstraction I get with Vue.js. It gives me a comprehensive set of functionality to do everything I want, without bugging me with all the nitty gritty implementation details of the underlying JavaScript. I can focus on features, which is exactly what we need to build our MVP.

Yet, not everything went smoothly at first. I ran into a well-documented issue when I wondered why some changes to a variable did not get picked up by Vue.js. Most likely, I had read about that limitation before, but when I implemented a new feature, I had forgotten about it. The change detection in arrays within Vue.js components is currently incomplete. There is an easy workaround, but figuring that out did cost me quite a bit of time.

As soon as I implemented the update of array values within the component the right way, the weird, somewhat random behaviour immediately disappeared and everything worked exactly as I expected it to work all the time.

Another standard practice that cost me a few days to resolve was the correct passing around of so called props across components. Again, this was not a difficult problem to fix, you just need to declare the things you need in the right places, but since I was still struggling with the basic concepts as a beginner with Vue.js, and pretty much with JavaScript in general, it took me longer than it should have to resolve this minor issue.

Developing efficient designs

Starting off with Vuetify was easier than with Vue.js, since many concepts and even a lot of the syntax is actually pretty close to Bootstrap in many ways. Of course, components and classes have different names, but the approach is similar, making it easy to transfer my Bootstrap knowledge over to Vuetify.

Like the Bootstrap grid, the Vuetify grid is also based on 12 columns, which often provides enough flexibility – but not always. Since the standardisation of flexbox, many grid-related tasks became much easier and better to control. That also means that diverging from the standard grid and implementing your own, non-12-column layouts got much simpler. However, mixing Vuetify flexbox grid components and raw HTML and CSS flexbox formatting proved challenging, since for a reason I still have not discovered, Vuetify components or even basic HTML elements simply vanished from the rendered page. Luckily, this wasn’t a problem, as those Vuetify components that disappeared were the ones that got replaced with the standard HTML and CSS markup anyway. Still, it left me a bit puzzled. As it did not matter, I did not investigate this further.

The more different libraries and tools you combine, the more complex the whole implementation gets. That’s why many developers aim to minimise dependencies. Not all features of all libraries work smoothly in any combination. For example, using Font Awesome class fa-2x to increase the size of symbols within a Vuetify <v-btn> button did not really work. Also, placing Font Awesome icons for services such as Facebook and Instagram in small round Vuetify proved challenging. With a bit of experimentation by deploying some padding commands of Vuetify, I could get the output close enough to what I wanted with icons neatly almost centred.

Embracing fine gems of Vue.js

I quickly became a fan of the Vue.js template syntax, which I find much nicer than just Mustache or the Django template language. This might be due to the fact that I am perhaps one of the few people who actually likes XML – I was sad when work on XHTML 2 was discontinued in favour of this sloppy, living HTML 5 specification.

Admittedly, mixing HTML-like syntax such as v-for and v-if for loops and conditions with Mustache-like variable syntax {{ }} could be confusing compared to a more “pure” approach, but it reminds me a tiny little bit of XSLT and I do like this, and find it easy to remember and convenient to use. For me, this is more intuitive.

It is most likely too early to say anything about Vue.js performance. But despite my most likely vastly sub-optimal JavaScript code, the application feels fast and smooth. Which is good enough for me for now. Using v-if repetitively and excessively is probably not the best way to go, but it provides a lot of flexibility and makes it easy and quick to adjust the output as needed.

One example where I was struck about how easy it was to add a completely new feature was when I integrated Markdown rendering for longer descriptions using the vue-markdown component. The ability to choose from a range of existing components and just add another dependency increased development speed substantially.

Another instance where I heavily benefitted from the components-based architecture of Vue.js was when I discovered that I could simply re-use a component I had built on two different pages. Just taking the component and adding it to another page greatly accelerated programming velocity.

Soon after implementing the first features, I decided to switch over from local data storage in the different components to Vuex – because most variables in a single component could be useful in other components too. For example, different presentations of events, list, search and calendar, could all use the same events list and events loading functions. Vuex seemed like the obvious solution to the challenge of making data easily accessible across different components and pages.

Once I moved things over to Vuex, getting clear about when to use actions and when mutations, and that for example actions can call other actions and more than one mutation, required another few blog articles and documentation pages.

The different options in Vuex, actions, mutations and getters in combination with the addition of convenience methods to access Vuex functions required a few refactoring runs. The more I understood the different concepts, the more I aligned my implementation with the standard practices and revisited architecture decisions I had made earlier. And I am sure I should refactor it again, but for now it works at least, so there is no need for immediate changes.

Adapting to a new approach to web apps

A benefit, that Vue.js probably shares with many other frameworks, is that the API and setup forces a certain structure on the developer. Maybe depending on your task, the default configuration and conventions are not the best fit, but I found these conventions and the general guidance about how to structure your app very helpful.

Vuetify reminded me lot of Bootstrap. The grid system and various helper classes make it easy to build a clean, responsive and mobile-friendly layout quickly. And while I am not a fan of all Material Design concepts, I do see benefits, especially for mobile users, in some of the design guidelines that are implemented in Vuetify, like button text in CAPITALS.

Maybe the biggest learning was that with Vue.js, it can often actually be quicker and easier to implement features in the front end which I first wanted to implement mainly in the backend. This reduces the complexity of the backend and also speeds up development, while making the application faster, and therefore, more user-friendly as well.

Improving our development setup

As of now, we still work without Webpack. Probably sooner rather than later, we should add the standard tooling to our workflow, to benefit from cross-compilation of JavaScript code and features like hot code reload.

However, what I view very positively is the fact that it is possible to use Vue.js without any additional tooling and configuration, helping users to get started quickly.

In our next article, we will look at the content of UnscrewMe, covering the kind of sources we use, the challenges we face when we collect information and what we learned so far from our data.

(Completing this article took a bit longer than planned – the writing process started over a rather average Gavi di Gavi from Italy, it’s just not my preferred kind of wine, I’m afraid. But this Gavi was followed by a French theme, starting with the very nice and smooth 2016 Vin de France Les Cotilles Pinot Noir by Domaine Roux Pere et Fils at the new Japanese restaurant Kazu in Fitzrovia. Over the Easter weekend, I continued to work on the text and paired the delightful and fun milk chocolate Easter bunny dessert at Ivy Cafe St. John’s Wood with their not outstanding but decent house white, the 2017 Grenache Blanc by Lierre from Languedoc in France. In addition, a day later or so at Randall & Aubin in Soho, I did some minor editing while enjoying a delicious 2016 Picpoul de Pinetfrom Domaine Roquemoliere, coincidentally also from Languedoc in France.)

--

--

Goetz Buerkle
UnscrewMe

Wine 🍷 (WSET Level 3), coffee ☕️, food 🍽, words 📔, languages 🇬🇧🇸🇪🇩🇪, Python 🐍, Django 🦄 , 🖥 Vue.js, entrepreneurship 🤔, startups 🚀 — London, UK.