Bulma, Vue and Webpack: oh my!
I’m working on a new project. Well, actually, no, it’s the rebuild of an old project. Written for PHP4/5 old. And yet, because I rock, still runs on PHP7. But… the front end, mobile responsiveness and overall functionality needs a polish and, well, complete re-build. This system has been running nicely for a decade – so let’s hope this rebuild can do just that too.
First of all, having built this site using Bulma, I really wanted to take advantage of its ease of use for developing, awesome responsiveness and flexible extension. So I started work making things look good, including responsive tables. So far, so good.
Up next was adding interactivity. And, well, because its what I know, went straight to jQuery.
I built an awesome responsive and collapsible navbar, a dialog helper to create modal and non-modal dialogs, plus a notifications helper to create alerts to display to the user. And all with some neat transitions. It just felt good.
But then I started to use a bit of Vue. I wanted to make another section be built using Vue – I’d done something similar before, so got that working. Then I built a table component that allows me to handle pagination and display of REST endpoints with optional data presentation processors (i.e. to concatenate data in to one column, other formatting, in case the REST endpoint doesn’t return it exactly how we want it).
But using Single File Components (which makes it so much simpler to manage HTML templates plus modularise code) requires they be parsed using something like Vue CLI or Webpack.
For years I have used CodeKit – such a handy tool for helping compile and minify (and auto-prefix) my LESS, SCSS and JS files. But it is MacOS only, so when working with a non-Mac developer, it made it hard.
I’d looked at Webpack in the past, but, um, yeah, wtf?
This time around, given I wanted to keep using Vue, I had a tinker with Vue CLI but I felt it was masking too much of the magic, and was pushing me down a path I didn’t want to go.
And so I went back to Webpack, and started at the beginning, and building my own config file.
And with some trial and error (and a heck of a lot of reading), I’ve got a config file that does exactly what I want it to do:
Single entry point JS (including SCSS)
Outputting CSS to its own file using Mini CSS Extract Plugin
Outputting to my public_html directory
Processing JS with babel
Processing my Vue Single File Components (.vue) with vue-loader
Compiling, auto-prefixing and minifying my SCSS with css-loader, postcss-loader, cssnano, autoprefixer and sass-loader
Creating a main.js file for app logic
Creating a vendor.js file for any of my node_modules
Hashed module IDs for production code
A few scripts including:
Build, to create production code
Dev, to create development code
Preview, to create production code WITHOUT hashing (just to keep an eye on file sizes)
Watch, to create development code and keep watching
And… handy MacOS notifications using Webpack Build Notifier Plugin
I’m really happy with this config file, and how it runs with Webpack 4. It’s such a flexible and intimidating system, but really happy its all running nicely.
So back to dev work.
Looking at all of the code I was writing, I’m only using jQuery for its (pretty awesome) selector engine plus some helpers for things like basic animations (slideUp/slideDown) plus adjusting CSS and class properties. Oh, and $.ajax.
But why am I still using jQuery for these (mostly) basic operations? Especially when working with Vue too which looks after the DOM for me.
For $.ajax, yeah there is fetch, but axios gets a better wrap, so rewrote my REST wrapper using axios. Boom. Done.
I then looked at writing some helpers functions in plain vanilla JS to act as shortcuts. I found DOMtastic and thought that was pretty good but… well… it’s still trying to be jQuery. What was I thinking?
Given I was enjoying writing both global and programmatic Components for Vue, I started to get a bit uneasy at having so many little Vue instances being generated around the app. It started to feel a bit messy.
So what if I create a wrapper around my entire code and run it as a single instance?
Yes, that works.
Vue is now doing the heavy lifting that jQuery was doing – adding classes based on state changes, adjusting layout as necessary, and all from a single instance.
Better yet, it was nicely using all of my Components and it just felt so simple to drop an entire dependency from my app. Basically anything I was doing in jQuery, I can accomplish using Vue, vanilla or a library (such as Axios for ajax calls).
But, there were times when I needed my components to talk to each other. Emit, On, Dispatch. Oh the documentation for Vue has changed so much – but finally found the recommendation I was after – Event Bus.
Before creating my main app, I have the Event Bus globally set – so everything can access it, including my Components. I can emit on the bus – and then listen on a component. And it all works so easily.
If I’m paying for the weight of the library to be included, why not take full advantage of the library.
Can I just say: Mind. Blown.
I still have a few more Components to build, but am really impressed with the ease of development and its performance (and light weight).
Was it scary to drop jQuery? Yes… but awesome without it.
Was it scary to learn Webpack? Yes… but why did I wait so long?
Was it scary to wrap everything in a single Vue instance? Of course… but it just works so nicely
And these past two weeks have been such an incredible learning exercise for me with not just “Hello World” tests, but real-world applications – and really coming forward in terms of modern front end web development.
The number of times I've done something, especially in Vue, using less lines of code than jQuery (in one helper vs component, my Vue version was less than half the number of lines), where I have then gone "oh my that is f**king cool" is off the charts. Ace.