2.5 KiB
2.5 KiB
title, impact, impactDescription, type, tags
| title | impact | impactDescription | type | tags | ||||||
|---|---|---|---|---|---|---|---|---|---|---|
| Async Component Best Practices | MEDIUM | Poor async component strategy can delay interactivity in SSR apps and create loading UI flicker | best-practice |
|
Async Component Best Practices
Impact: MEDIUM - Async components should reduce JavaScript cost without degrading perceived performance. Focus on hydration timing in SSR and stable loading UX.
Task List
- Use lazy hydration strategies for non-critical SSR component trees
- Import only the hydration helpers you actually use
- Keep
loadingComponentdelay near the default200msunless real UX data suggests otherwise - Configure
delayandtimeouttogether for predictable loading behavior
Use Lazy Hydration Strategies in SSR
In 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,
hydrateOnVisible,
hydrateOnIdle
} from 'vue'
const AsyncComments = defineAsyncComponent({
loader: () => import('./Comments.vue'),
hydrate: hydrateOnVisible({ rootMargin: '100px' })
})
const AsyncFooter = defineAsyncComponent({
loader: () => import('./Footer.vue'),
hydrate: hydrateOnIdle(5000)
})
</script>
Prevent Loading Spinner Flicker
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 LoadingSpinner from './LoadingSpinner.vue'
import ErrorDisplay from './ErrorDisplay.vue'
const AsyncDashboard = defineAsyncComponent({
loader: () => import('./Dashboard.vue'),
loadingComponent: LoadingSpinner,
errorComponent: ErrorDisplay,
delay: 200,
timeout: 30000
})
</script>
Delay Guidelines
| Scenario | Recommended Delay |
|---|---|
| Small component, fast network | 200ms |
| Known heavy component | 100ms |
| Background or non-critical UI | 300-500ms |