Improving the Vue workflow

August 25, 2020

On my latest project here at Tome, I have been learning the ropes of the amazing Vue framework. It’s been a joy to learn and work with. But like all frontend frameworks, defining a consistent and useful build/linting workflow for an SPA app can be a huge undertaking. You have to deal with the module bundling, the cross-browser support, the transpiling, and so on. This has been further complicated by our usage of the equally amazing TypeScript in our project. We used some very good tools to handle all of these problems, but I was never able to get it to a satisfying state. I decided to use my Lab Day to address this for future projects.


But first, a summary of our current Vue workflow. Our core tools are Vue CLI and Vetur. Vue CLI is a great standard tool to use for Vue apps. It’s plugin system ensures that we get a working Webpack pipeline without having to touch any Webpack configuration. It even comes with a nice UI interface! Vetur is a Visual Studio Code plugin that allows for linting, autocompletion, and all the other nice things you expect from your IDE. Why a custom plugin? Because Vue allows for Single File Components (SFC), a custom file type that has template, style, and script sections to keep your components organized in one place. This needs special compilation considerations that Vetur conveniently handles.


Now this workflow is all well and good, but when TypeScript is brought into the equation, it starts stumbling over itself. The key issue is that Vue CLI uses a different TypeScript linter (tslint) then the ones supported by Vetur. There is also no way to configure it to use a proper linter. This leads to a very different lint result than what is reflected in the IDE. None of the errors in the screenshot below appear in IDE! This makes it a headache to address these things quickly (or even be aware of them sometimes).

So the first order of business was to fix this issue. This ended up being a relatively small change to execute, but a very annoying one to figure out. It involved adjusting the .eslintrc.js file to use some typescript extensions that closely approximate the tslint rules that the TypeScript plugin compilation uses. It also required some custom configuration for the Vetur plugin to force validation to happen. There may be some subtle differences in the rulesets until such a time where the plugin is extended to allow for different linting, but now the linting experience is accurately reflected in our IDE!

That was the root problem with our current workflow, but I also took the times to polish other aspects. I added autofixing on save for linting. I leveraged the extensions.json file that VS Code parses to make sure any new project contributors get suggested the plugins they need to get the same experience. I even discovered an experimental Vetur configuration that allows for even better autocomplete of component variables in template! I took all these changes, bundled them up, and registered the results as a starter project so that everyone else at Tome can go fast on Vue. I also became a bit more familiar with the guts of what makes a modern Vue project.