Pulled ALL skills from 15 source repositories: - anthropics/skills: 16 (docs, design, MCP, testing) - obra/superpowers: 14 (TDD, debugging, agents, planning) - coreyhaines31/marketingskills: 25 (marketing, CRO, SEO, growth) - better-auth/skills: 5 (auth patterns) - vercel-labs/agent-skills: 5 (React, design, Vercel) - antfu/skills: 16 (Vue, Vite, Vitest, pnpm, Turborepo) - Plus 13 individual skills from various repos Mosaic Stack is not limited to coding — the Orchestrator and subagents serve coding, business, design, marketing, writing, logistics, analysis, and more. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
3.8 KiB
3.8 KiB
Use suspensible Prop for Nested Suspense (Vue 3.3+)
Rule
When nesting <Suspense> components, use the suspensible prop on the inner Suspense to properly coordinate with the parent Suspense. Without this prop, nested async components may render empty nodes until resolved instead of showing fallback content.
Why This Matters
Without the suspensible prop, the inner <Suspense> is treated as a synchronous component by the parent. This causes:
- Empty nodes appearing briefly during async resolution
- Multiple patching cycles as the component tree updates
- Inconsistent loading states that confuse users
Bad Code
<template>
<Suspense>
<component :is="DynamicAsyncOuter">
<!-- DynamicAsyncInner renders EMPTY until resolved! -->
<component :is="DynamicAsyncInner" />
</component>
<template #fallback>
Loading...
</template>
</Suspense>
</template>
<template>
<Suspense>
<OuterLayout>
<!-- Inner Suspense not coordinated with parent -->
<Suspense>
<AsyncWidget />
<template #fallback>Loading widget...</template>
</Suspense>
</OuterLayout>
<template #fallback>
Loading layout...
</template>
</Suspense>
</template>
Good Code
<template>
<Suspense>
<component :is="DynamicAsyncOuter">
<!-- Inner Suspense with suspensible prop -->
<Suspense suspensible>
<component :is="DynamicAsyncInner" />
<template #fallback>
<InnerLoadingState />
</template>
</Suspense>
</component>
<template #fallback>
<OuterLoadingState />
</template>
</Suspense>
</template>
Complex Layout Example
<template>
<Suspense>
<DashboardLayout>
<template #sidebar>
<!-- Sidebar has its own Suspense boundary -->
<Suspense suspensible>
<AsyncSidebar />
<template #fallback>
<SidebarSkeleton />
</template>
</Suspense>
</template>
<template #main>
<!-- Main content has its own Suspense boundary -->
<Suspense suspensible>
<AsyncMainContent :key="contentKey" />
<template #fallback>
<ContentSkeleton />
</template>
</Suspense>
</template>
<template #widgets>
<!-- Each widget can load independently -->
<Suspense suspensible>
<AsyncWidgets />
<template #fallback>
<WidgetsSkeleton />
</template>
</Suspense>
</template>
</DashboardLayout>
<template #fallback>
<FullPageLoader />
</template>
</Suspense>
</template>
How suspensible Works
| Configuration | Behavior |
|---|---|
No suspensible prop |
Inner Suspense treated as sync; parent doesn't wait for inner async deps |
suspensible on inner |
Inner async deps bubble up to parent Suspense for coordinated loading |
When to Use Nested Suspense
Use nested Suspense with suspensible when:
- Different page sections should show their own loading states
- You want granular control over which parts show loading indicators
- Sections can load at different speeds and should update independently
Avoid nested Suspense when:
- A single loading state for the whole component is sufficient
- The complexity isn't worth the UX benefit
- You're targeting Vue versions before 3.3
Key Points
- Always add
suspensibleprop when nesting Suspense components - Without
suspensible, expect empty nodes and multiple patching cycles - This feature requires Vue 3.3 or later
- Use nested Suspense boundaries strategically for better UX, not everywhere
- Each Suspense can have its own fallback for section-specific loading states