Switching from React To Vue.js: don't lock yourself in
Tags: vue
Published: 2021-03-19 14:52:39


This year I happened to onboard a **Vue.js** based company after several years of mainly **React** related activities. This is how I managed to approach this new ecosystem.

*These notes are a work in progress. I'll keep them updated as long as I get familiar with Vue ecosystem.*

### Stay away from Vue cli tools

Vue provides a [set of optional cli integrations](https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue) to provide additional plug-and-play functionalities to the core one. Most of them are not extensible and poorly maintained.

My suggestion is to ignore them and use universal tools configured to work with Vue (eg. `jest` instead of `@vue/cli-plugin-unit-jest`, `eslint` instead of `@vue/cli-plugin-eslint`).

I'm currently just using `vue-cli-service` dev server to run my development environment. Compile with Rollup (even though [`rollup-plugin-vue`](https://github.com/vuejs/rollup-plugin-vue) is still quite flaky).

### Vue + Typescript
Vue (at least v2) and Vue's *Single File Components* don't play nice with Typescript, but luckily there are tools that can partially fill this gap.

#### Vuex + Typescript
If using Vuex these helper libraries can help to bring store types into your components:

- [typed-vuex](https://github.com/danielroe/typed-vuex)
- [vuex-typescript](https://github.com/istrib/vuex-typescript)
- [vuex-typex](https://github.com/mrcrowl/vuex-typex)

I eventually opted for **Typed Vuex**, which seems to be the current de facto official Vuex/TypeScript library. It definitely does its job with a minimal impact over the existing codebase.

The only minor downside consists on the fact that every component connected to the store is supposed to import a `storeAccessor` object exposed by the same store instance used by the application. Not a real blocker in my opinion.

#### Type checking Vue components

Vue components (and especially their *Vue Template Syntax*) are unfortunately invisible to typescript.

[Vetur](https://marketplace.visualstudio.com/items?itemName=octref.vetur) and [VueDX](https://github.com/znck/vue-developer-experience) (*still in alpha*) expose 2 **cli component type checkers** which I've not been able to use with a Vue 2 project:

- [vti](https://vuejs.github.io/vetur/guide/vti.html)
- [TypeCheck for Vue
](https://github.com/znck/vue-developer-experience/tree/main/packages/typecheck)

Luckily Vetur provides a working component **type checking in VSC** by enabling experimental template interpolation service in your config:

```
vetur.experimental.templateInterpolationService: true
```
...not the best solution but better then nothing.

#### Replacing Vue template with tsx

Since Vue 2 type checking experience turned out to be quite a failure, I considered the option of skipping Vue templates (and Single File Component pattern) and just use TSX, which is type checkable by definition.

I've found a [very promising library](https://github.com/wonderful-panda/vue-tsx-support) which provides the necessary glue between Vue and Typescript + TSX. 

I've toyed with `vue-tsx-support` a couple hours with encouraging results, but I couldn't actually suggest my team to base our project on a library not officially supported by Vue.

### Write framework-agnostic tests

When it comes to write unit tests, don't lock yourself into Vue ecosystem but use an abstraction on top of this.

I'm using [`vue-testing-library`](https://github.com/testing-library/vue-testing-library) with [`msw`](https://mswjs.io/) (to mock network responses) and it works as well as `react-testing-library`.

### General considerations

Vue ecosystem is not mature as React's. A significant number of Vue-specific libraries are solo projects with uncertain present and future.

As a general approach I'm trying to rely on Vue ecosystem only for what is strictly necessary and find a way of using tools built outside of Vue realm. On the long term I expect Vue to open to established standards of web frontend industry.

Just an example. Vue's [Single File Component pattern](https://vuejs.org/v2/guide/single-file-components.html) seems a good idea in the first half hour, until you realize it places your code out of any language standard, preventing any third party tool from being able to parse it.