Loading source
Pulling the file list, source metadata, and syntax-aware rendering for this listing.
Source from repo
Vue 3 debugging reference for reactivity issues, computed errors, watcher bugs, async failures, and SSR hydration problems.
Files
Skill
Size
Entrypoint
Format
Open file
Syntax-highlighted preview of this file as included in the skill package.
reference/sfc-named-exports-forbidden.md
1---2title: SFC Script Block Must Use Default Export Only3impact: HIGH4impactDescription: Named exports in SFC script blocks will fail silently or cause build errors - Vue expects exactly one default export5type: gotcha6tags: [vue3, sfc, export, script-block, composition-api]7---89# SFC Script Block Must Use Default Export Only1011**Impact: HIGH** - Vue Single-File Components expect exactly one default export from the `<script>` block. Using named exports for your component will cause build failures or runtime errors because Vue's tooling is designed to process a single default-exported component definition per `.vue` file.1213## Task Checklist1415- [ ] Always use `export default` in `<script>` blocks (Options API)16- [ ] Use `<script setup>` which handles exports automatically (Composition API)17- [ ] Move shared utilities to separate `.js`/`.ts` files, not the component's script block18- [ ] If you need to export types, use a separate `<script>` block alongside `<script setup>`1920**Problematic Code:**21```vue22<!-- MyComponent.vue -->23<script>24// BAD: Named exports don't work for the component itself25export const MyComponent = {26data() {27return { count: 0 }28}29}3031// BAD: Exporting multiple things from component script32export const CONSTANT = 4233export function helper() { }34</script>3536<template>37<div>{{ count }}</div>38</template>39```4041**Correct Code:**42```vue43<!-- MyComponent.vue - Options API -->44<script>45// GOOD: Single default export46export default {47data() {48return { count: 0 }49}50}51</script>5253<template>54<div>{{ count }}</div>55</template>56```5758```vue59<!-- MyComponent.vue - Composition API with script setup -->60<script setup>61// GOOD: No export needed, component is auto-exported62import { ref } from 'vue'6364const count = ref(0)65</script>6667<template>68<div>{{ count }}</div>69</template>70```7172## Exporting Types Alongside Script Setup7374For TypeScript, use a separate regular script block for type exports:7576```vue77<script lang="ts">78// Regular script block for exports79export interface User {80id: number81name: string82}8384export type Status = 'pending' | 'active' | 'inactive'85</script>8687<script setup lang="ts">88// Setup script for component logic89import { ref } from 'vue'9091const users = ref<User[]>([])92</script>9394<template>95<ul>96<li v-for="user in users" :key="user.id">{{ user.name }}</li>97</ul>98</template>99```100101## Sharing Utilities Across Components102103Don't put shared code in component script blocks. Create separate files:104105```typescript106// utils/constants.ts107export const ITEMS_PER_PAGE = 20108export const API_BASE_URL = '/api/v1'109110// utils/helpers.ts111export function formatDate(date: Date): string {112return date.toLocaleDateString()113}114115export function formatCurrency(amount: number): string {116return `$${amount.toFixed(2)}`117}118```119120```vue121<!-- ProductList.vue -->122<script setup>123// GOOD: Import shared utilities from external files124import { ITEMS_PER_PAGE } from '@/utils/constants'125import { formatCurrency } from '@/utils/helpers'126import { ref } from 'vue'127128const products = ref([])129</script>130```131132## Why This Restriction Exists133134Vue's SFC compiler and build tools expect:1351361. **One component per file**: The `.vue` file format is designed for single-component definitions1372. **Predictable structure**: Tools like Volar, vue-tsc, and bundler plugins assume default export1383. **Hot Module Replacement**: HMR relies on the single-component-per-file convention139140```javascript141// How Vue tooling processes SFCs internally142import MyComponent from './MyComponent.vue'143// ^ Always expects the default export to be the component144```145146## Common Mistake: Reusing Code via SFC Exports147148```vue149<!-- BAD PATTERN: Trying to reuse code from components -->150<script>151// This won't work as expected152export const sharedLogic = () => { ... }153154export default {155// component definition156}157</script>158```159160Instead, use composables:161162```typescript163// composables/useSharedLogic.ts164export function useSharedLogic() {165// Shared reactive logic166const state = ref(0)167const increment = () => state.value++168169return { state, increment }170}171```172173```vue174<!-- ComponentA.vue -->175<script setup>176import { useSharedLogic } from '@/composables/useSharedLogic'177178const { state, increment } = useSharedLogic()179</script>180```181182## Reference183- [Vue.js SFC Specification](https://vuejs.org/api/sfc-spec.html)184- [Vue.js Composition API - Composables](https://vuejs.org/guide/reusability/composables.html)185