- Debian-based api image (bookworm-slim), docker/debian mirrors, prisma binaryTargets for openssl 3.0 - nginx: admin SPA under /admin, TLS via acme.sh (ZeroSSL) + auto-renewal cron, http->https redirect - prisma: add origin_goods.delisted migration, sync missing schema (good_image/tag_font_color/good_tags), fix users.createdAt Timestamptz - api: CORS wildcard reflection, helmet CORP cross-origin, price backfill in persistProductDetail, categoryIcon ancestor fallback, mediaByColor per-color gallery in public goods detail - admin: /admin base path (vite + router) - import-data.mjs: udt_name casting, serial sequence advance fix
2.6 KiB
2.6 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 |