Web Development6 min read

Vue.js

Progressive JavaScript framework with Composition API, single-file components, and Pinia state - approachable for small apps, scalable for enterprise SPAs.

Vue.jsComposition APIPiniaViteJavaScript

skill: Vue.js category: Web Development tags: [Vue.js, Composition API, Pinia, Vite, JavaScript] readingTime: 6

Vue 3 with Composition API is the standard for new Vue projects. Prefer Vue when your team finds React's JSX cognitive overhead high or needs Options API migration path. For server rendering use Nuxt. For React-familiar teams, React or Next.js may be a better fit.

Workflow

  1. Scaffold with Vitecreate-vue sets up Vite, TypeScript, Pinia, and Vue Router with a single command - faster than webpack-based setups.
  2. Write single-file components with <script setup><script setup> is compile-time sugar for Composition API - variables declared are automatically exposed to the template, reducing boilerplate.
  3. Manage global state with PiniaPinia replaces Vuex - no mutations, full TypeScript inference, devtools integration, and simpler composition store API.
  4. Route with Vue Router 4Vue Router 4 is async-first - lazy loading routes reduces initial bundle size.
  5. Compose reusable logic with composablesComposables (like React hooks) encapsulate reactive state and side effects in plain functions - shareable across components without mixins.

Output Format

Vue 3 SPA with Composition API, Pinia, Vue Router, and Vite.

my-app/
├── src/
│   ├── main.ts
│   ├── App.vue
│   ├── views/         # Route-level pages
│   ├── components/    # Reusable UI
│   ├── stores/        # Pinia stores
│   ├── composables/   # Shared logic
│   └── router/        # Vue Router config
└── vite.config.ts

Examples

Input

Output

Input

Output

Edge Cases & Gotchas

  • ref vs reactive - ref() wraps primitives (access with .value); reactive() wraps objects (access directly). Mixing them inconsistently causes confusing bugs.
  • Watchers on reactive objects - watch(obj, cb) won't fire on nested property changes unless you pass { deep: true } or use watchEffect.
  • Pinia store reset - Call store.$reset() to reset to initial state - only works with Options-style stores. Composition stores need a manual reset function.
  • SSR hydration mismatch - Server-rendered HTML differs from client-rendered output when using Date.now() or Math.random() in setup - these produce different values on server vs client.

When to Break These Rules

  • Use Nuxt instead of plain Vue when SEO, SSR, or file-based routing are required.
  • Use React or Svelte when team familiarity or ecosystem fit matters more than Vue's progressive enhancement philosophy.

Reference Files

  • https://vuejs.org/guide/introduction
  • https://pinia.vuejs.org/

More skills in this library

Browse all technical skills - Mobile, AI/ML, Web, Backend, Design, and Product.