5 best practices for developing with Vue 3

The five best practices for developing with Vue in 2026 are: write components with the Composition API and <script setup>, build with Vite, keep shared state in Pinia, use TypeScript with typed props, and test with Vitest while staying on a supported version. All five follow the current guidance on vuejs.org, and together they describe what a well-kept Vue 3 codebase looks like.

Vue is a JavaScript framework for building the part of a web application that users see and click. This article is written for developers, and for the person paying them who wants to know what good looks like. Each practice ends with the reason it matters to the business.

Why the advice has changed

Most Vue advice still found online was written for Vue 2, which reached end of life on 31 December 2023. Vue 3 is the current major version, and the latest stable release is 3.5. Several tools that were standard in the Vue 2 years have been superseded:

Vue 2 eraCurrent practice
Options API everywhereComposition API with <script setup> for applications
Mixins for shared logicComposables
Vue CLI (webpack)Vite, set up with create-vue
VuexPinia
Vetur editor extensionVue - Official extension
JestVitest

A codebase that still uses the left-hand column is not broken, but it tells you when it was last given attention.

The five practices

1. Use the Composition API with script setup

Vue offers two ways to write a component. The older Options API arranges code by type: data in one block, methods in another. The Composition API arranges it by feature, so everything to do with, say, searching a customer list sits together. The Vue documentation recommends the Composition API with single-file components (one .vue file holding a component’s template, logic and styles) for anyone building a full application.

<script setup> is the short form of the Composition API and the one to use by default:

<script setup lang="ts">
import { computed, ref } from 'vue'
import type { Order } from './types'

const props = defineProps<{ customerId: number; orders: Order[] }>()
const search = ref('')
const matching = computed(() =>
  props.orders.filter((o) => o.reference.includes(search.value))
)
</script>

Logic that several components need goes into a composable, a function whose name starts with use, such as useOrders(). Composables replace mixins, which the Vue team no longer recommends because it becomes unclear where a property came from once a component uses several of them.

The Options API has not been deprecated and the Vue team says it has no plan to remove it. There is no need to convert working components for the sake of it. Pick one style for new code and keep to it.

Why it matters: code organised by feature is quicker for a new developer to follow, which is what keeps a change of supplier or a new hire from becoming expensive.

2. Build with Vite

Vite is the build tool that turns source files into what the browser loads. New projects should be created with the official scaffolding command, npm create vue@latest, which sets up Vite and offers TypeScript, routing, Pinia and testing as options. Vue CLI, the older webpack-based tool, is in maintenance mode, and the Vue documentation recommends Vite for new projects.

Why it matters: an application still on Vue CLI will keep building for now, but it sits on tooling that is no longer being developed. Moving to Vite is usually a contained piece of work and worth doing before it is forced.

3. Keep shared state in Pinia, and only shared state

State is the data an application holds while it runs: who is logged in, what is in the basket. When many components need the same data, it belongs in a store. Pinia is the store library the Vue team recommends. Vuex, its predecessor, is in maintenance mode and receives no new features.

The discipline is in what stays out. Data used by one component belongs in that component. Data fetched for one screen belongs to that screen. A store that holds everything becomes the place where every bug has to be hunted.

Why it matters: misplaced state is one of the commoner reasons a small change in one screen breaks another.

4. Use TypeScript, typed props and the official style rules

TypeScript adds type checking to JavaScript, so that passing a customer name where a customer number was expected is caught before the code runs. Vue itself is written in TypeScript. With <script setup lang="ts">, the props a component accepts are declared with their types, as in the example above, and the vue-tsc tool checks the whole project from the command line.

The Vue style guide lists a handful of rules it calls essential:

  • give components multi-word names, so they cannot clash with HTML elements;
  • define props in detail, with at least a type;
  • always give a key to items rendered with v-for;
  • never put v-if and v-for on the same element;
  • scope each component’s styles so they cannot leak.

eslint-plugin-vue, maintained by the Vue team, enforces these automatically. Run it, and vue-tsc, on every change before it is merged.

One security rule belongs here too. Vue escapes text it displays, which blocks the commonest form of script injection, but v-html switches that protection off. Use it only with content you fully control, never with anything a user typed.

Why it matters: rules enforced by a tool do not depend on any one developer remembering them.

5. Test, and stay on a supported version

For unit and component tests the Vue documentation recommends Vitest, which shares Vite’s configuration, together with @vue/test-utils. For end-to-end tests, which drive the application through a real browser as a user would, it recommends Playwright or Cypress. A sensible minimum is unit tests around the business rules and an end-to-end test for each process the business depends on.

Tests are also what make upgrades cheap. Vue has no fixed release schedule: patch releases appear as needed and minor versions from time to time, and a codebase with tests can take each one with little effort. One detail to know: Vue’s type definitions can change between minor versions, so pin the minor version and upgrade deliberately.

Why it matters: small, regular upgrades are a routine part of software maintenance. Skipped for years, they turn into a project.

If the application is still on Vue 2

Vue 2 no longer receives fixes of any kind, including security fixes. The Vue team sets out the options:

  • move to Vue 3, which is the recommended route;
  • at the very least, update to 2.7.16, the final Vue 2 release;
  • buy extended support from a third party if you cannot move yet.

Vue 3 is not a drop-in replacement. It contains breaking changes, and libraries written for Vue 2 often need replacing, so the migration should be planned screen by screen with tests in place first. Our page on running unsupported software covers how to weigh the risk in the meantime.

What to ask if you are paying for the work

You do not need to read the code to check most of this. Ask whoever maintains the application:

  • Which version of Vue is in package.json, and when was it last updated?
  • Is the build Vite or Vue CLI?
  • Is state held in Pinia or Vuex?
  • Do the type check, the linter and the tests run automatically on every change?
  • How many end-to-end tests are there, and which processes do they cover?

Vague answers are a finding in themselves. If you want an independent view, a code audit reports on exactly these points in plain English. To see how Vue compares with the alternatives, read the advantages of Vue.js.

Tell us about your system

Say what it does, what it is built on and what is worrying you. We will reply with what we would look at first and whether we are the right people to help.

Tell us about your system 0800 433 7990 Monday to Friday, 9am to 5pm. A first 20-minute call is free, and we reply to every enquiry within one working day. What happens after you get in touch