.agents/skills/vue-best-practices/references/component-async.md
Impact: MEDIUM - Async components should reduce JavaScript cost without degrading perceived performance. Focus on hydration timing in SSR and stable loading UX.
loadingComponent delay near the default 200ms unless real UX data suggests otherwisedelay and timeout together for predictable loading behaviorIn Vue 3.5+, async components can delay hydration until idle time, visibility, media query match, or user interaction.
BAD:
<script setup lang="ts">
import { defineAsyncComponent } from 'vue'
const AsyncComments = defineAsyncComponent({
loader: () => import('./Comments.vue')
})
</script>
GOOD:
<script setup lang="ts">
import {
defineAsyncComponent,
hydrateOnIdle,
hydrateOnVisible
} from 'vue'
const AsyncComments = defineAsyncComponent({
loader: () => import('./Comments.vue'),
hydrate: hydrateOnVisible({ rootMargin: '100px' })
})
const AsyncFooter = defineAsyncComponent({
loader: () => import('./Footer.vue'),
hydrate: hydrateOnIdle(5000)
})
</script>
Avoid showing loading UI immediately for components that usually resolve quickly.
BAD:
<script setup lang="ts">
import { defineAsyncComponent } from 'vue'
import LoadingSpinner from './LoadingSpinner.vue'
const AsyncDashboard = defineAsyncComponent({
loader: () => import('./Dashboard.vue'),
loadingComponent: LoadingSpinner,
delay: 0
})
</script>
GOOD:
<script setup lang="ts">
import { defineAsyncComponent } from 'vue'
import ErrorDisplay from './ErrorDisplay.vue'
import LoadingSpinner from './LoadingSpinner.vue'
const AsyncDashboard = defineAsyncComponent({
loader: () => import('./Dashboard.vue'),
loadingComponent: LoadingSpinner,
errorComponent: ErrorDisplay,
delay: 200,
timeout: 30000
})
</script>
| Scenario | Recommended Delay |
|---|---|
| Small component, fast network | 200ms |
| Known heavy component | 100ms |
| Background or non-critical UI | 300-500ms |