Awesome-omni-skill vuejs-best-practices
Vue 3 and Nuxt 3 performance optimization and best practices. This skill should be used when writing, reviewing, or refactoring Vue.js code to ensure optimal performance patterns. Triggers on tasks involving Vue components, Nuxt pages, Composition API, Pinia state management, or performance improvements.
install
source · Clone the upstream repo
git clone https://github.com/diegosouzapw/awesome-omni-skill
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/diegosouzapw/awesome-omni-skill "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/development/vuejs-best-practices" ~/.claude/skills/diegosouzapw-awesome-omni-skill-vuejs-best-practices-437977 && rm -rf "$T"
manifest:
skills/development/vuejs-best-practices/SKILL.mdsource content
Vue.js Best Practices
Comprehensive performance optimization guide for Vue 3 and Nuxt 3 applications. Contains 50+ rules across 10 categories, prioritized by impact to guide automated refactoring and code generation.
When to Apply
Reference these guidelines when:
- Writing new Vue 3 components or Nuxt 3 pages
- Using Composition API and composables
- Implementing data fetching (client or server-side)
- Managing state with Pinia
- Reviewing code for performance issues
- Refactoring existing Vue/Nuxt code
- Optimizing bundle size or load times
Rule Categories by Priority
| Priority | Category | Impact | Prefix |
|---|---|---|---|
| 1 | Reactivity Optimization | CRITICAL | |
| 2 | Bundle Size Optimization | CRITICAL | |
| 3 | Nuxt 3 Server Performance | HIGH | |
| 4 | Component Design Patterns | HIGH | |
| 5 | Composition API Patterns | MEDIUM-HIGH | |
| 6 | State Management (Pinia) | MEDIUM-HIGH | |
| 7 | Rendering Performance | MEDIUM | |
| 8 | TypeScript Integration | MEDIUM | |
| 9 | Testing Patterns | LOW-MEDIUM | |
| 10 | Advanced Patterns | LOW | |
Quick Reference
1. Reactivity Optimization (CRITICAL)
- Use shallowRef for large objects that don't need deep reactivityreactivity-shallowref
- Use shallowReactive for flat objectsreactivity-shallowreactive
- Leverage computed for expensive calculations (auto-caching)reactivity-computed-cache
- Use toRaw() when passing to external librariesreactivity-toraw
- Use markRaw() for non-reactive objects (classes, third-party instances)reactivity-markraw
- Use effectScope() to batch cleanup of effectsreactivity-effectscope
2. Bundle Size Optimization (CRITICAL)
- Import from 'vue' not internal packages (@vue/reactivity, @vue/runtime-core)bundle-tree-shaking
- Use defineAsyncComponent for heavy componentsbundle-async-components
- Dynamic import() for route-level code splittingbundle-dynamic-imports
- Import icons directly, avoid icon libraries barrel filesbundle-icon-imports
- Use lodash-es with specific importsbundle-lodash-es
- Use rollup-plugin-visualizer to identify bloatbundle-analyze
- Externalize large libraries to CDN when appropriatebundle-external-cdn
3. Nuxt 3 Server Performance (HIGH)
- Use useFetch/useAsyncData for SSR-friendly data fetchingnuxt-usefetch
- Prefix with Lazy for automatic lazy loadingnuxt-lazy-components
- Minimize payload with pick/transform optionsnuxt-payload-reduce
- Use routeRules for caching strategiesnuxt-cache-route
- Use .server.vue for server-only componentsnuxt-server-components
- Prerender static pages at build timenuxt-prerender
- Use Nuxt Islands for partial hydrationnuxt-islands
- Leverage Nitro caching for API routesnuxt-nitro-cache
4. Component Design Patterns (HIGH)
- Always usecomponent-sfc-setup
syntax<script setup>
- Use destructuring with defineProps for reactivitycomponent-props-destructure
- Always define emits with TypeScriptcomponent-emits-typed
- Type slots with defineSlotscomponent-slots-typed
- Use defineExpose sparingly, prefer props/emitscomponent-expose
- Use v-once for static contentcomponent-v-once
- Use v-memo for list item optimizationcomponent-v-memo
- Use Teleport for modals/tooltipscomponent-teleport
5. Composition API Patterns (MEDIUM-HIGH)
- Prefix composables with 'use' (useAuth, useFetch)composable-naming
- Return object, not array, for better DXcomposable-return-object
- Always handle cleanup in onUnmountedcomposable-cleanup
- Handle async state properly (loading, error, data)composable-async
- Checkcomposable-ssr-safe
for browser-only codeimport.meta.client
- Use provide/inject with InjectionKey for type safetycomposable-provide-inject
- Leverage VueUse before writing custom composablescomposable-vueuse
6. State Management - Pinia (MEDIUM-HIGH)
- Prefer setup stores over options storespinia-setup-syntax
- Use storeToRefs() to maintain reactivitypinia-storetorefs
- Use actions for async operations, not getterspinia-actions-async
- Use pinia-plugin-persistedstate for persistencepinia-persist
- Implement $reset for store cleanuppinia-reset
- Use $subscribe for side effectspinia-subscribe
- Handle SSR hydration properly in Nuxtpinia-ssr-hydration
7. Rendering Performance (MEDIUM)
- v-show for frequent toggles, v-if for rare conditionsrendering-v-show-v-if
- Always use unique :key in v-for (avoid index as key)rendering-key-attribute
- Use virtual scrolling for long lists (100+ items)rendering-virtual-scroll
- Cache component instances with KeepAliverendering-keep-alive
- Use Suspense for async component loading statesrendering-suspense
8. TypeScript Integration (MEDIUM)
- Define props with interface, not typetypescript-props-interface
- Explicitly type refs:typescript-ref-typeref<string>('')
- Type template refs:typescript-template-refref<HTMLInputElement | null>(null)
- Usetypescript-component-type
for component refsComponentPublicInstance
- Use generic components for reusable patternstypescript-generic-components
- Use InjectionKey<T> for type-safe provide/injecttypescript-strict-inject
- Type event handlers properlytypescript-event-handlers
9. Testing Patterns (LOW-MEDIUM)
- Use Vitest for unit testing (Vue ecosystem native)testing-vitest
- Use @vue/test-utils for component testingtesting-vue-test-utils
- Test composables in isolationtesting-composables
- Use createTestingPinia for store testingtesting-pinia
- Use MSW for API mockingtesting-msw
- Use Playwright for E2E with Nuxttesting-playwright
10. Advanced Patterns (LOW)
- Use render functions for dynamic component generationadvanced-render-function
- Create custom directives for DOM manipulationadvanced-custom-directive
- Structure plugins with proper install functionadvanced-plugin-pattern
Decision Trees
When to use ref vs reactive
What type of data? │ ├── Primitives (string, number, boolean) │ └── ref() ✓ │ ├── Objects/Arrays (need deep reactivity) │ └── reactive() ✓ │ ├── Large objects (performance critical) │ └── shallowRef() or shallowReactive() ✓ │ └── Non-reactive data (class instances, external libs) └── markRaw() ✓
When to use useFetch vs $fetch (Nuxt)
Where is the code running? │ ├── Component/Page (need SSR + reactivity) │ └── useFetch() or useAsyncData() ✓ │ ├── Server API route │ └── $fetch() ✓ │ ├── Event handler (client-side only) │ └── $fetch() ✓ │ └── Composable (reusable) └── useFetch() with key ✓
Component communication pattern
What's the relationship? │ ├── Parent → Child │ └── Props ✓ │ ├── Child → Parent │ └── Emits ✓ │ ├── Siblings │ └── Pinia store or provide/inject ✓ │ ├── Deep nesting (prop drilling) │ └── provide/inject ✓ │ └── Global state └── Pinia store ✓
Anti-Patterns to Avoid
❌ DON'T:
- Use Options API in new Vue 3 projects
- Mutate props directly
- Use
inthis<script setup> - Create reactive() with primitives
- Use v-if and v-for on same element
- Forget :key in v-for loops
- Use index as :key for dynamic lists
- Access refs without .value in script
- Nest Pinia stores unnecessarily
- Use
in components (use$fetch
)useFetch
✅ DO:
- Use Composition API with
<script setup> - Define props and emits with TypeScript
- Use computed for derived state
- Use watchEffect for side effects
- Leverage VueUse composables
- Use Pinia for global state
- Handle loading/error states
- Clean up effects in onUnmounted
- Use Suspense for async components
Performance Checklist
Before shipping:
- Bundle analyzed? No unexpected large dependencies
- Lazy loading? Routes and heavy components code-split
- Reactivity optimized? Using shallowRef where appropriate
- SSR working? No hydration mismatches
- Images optimized? Using nuxt/image or similar
- API calls deduplicated? Using useFetch with proper keys
- State management efficient? Not over-fetching in stores
- List rendering optimized? Virtual scroll for long lists
Full Compiled Document
For detailed code examples, implementation patterns, and comprehensive explanations:
AGENTS.md
Each section in AGENTS.md contains:
- Detailed explanations of why patterns matter
- Incorrect vs Correct code comparisons
- Copy-paste ready implementations
- Vue 3 and Nuxt 3 specific examples
- VueUse integration examples