No description
|
Some checks failed
Publish / publish (push) Failing after 0s
Co-Authored-By: Lilith Autocommit <noreply@atlilith.com> |
||
|---|---|---|
| .forgejo/workflows | ||
| src | ||
| .gitignore | ||
| IDEAS.md | ||
| package.json | ||
| README.md | ||
| tsconfig.json | ||
@lilith/ui-lazy
SOLID/DRY lazy loading utilities for React. Defer heavy dependencies and reduce initial bundle size for consumer-facing applications.
Installation
pnpm add @lilith/ui-lazy
Usage
Factory Pattern (Recommended)
import { createLazyComponent, createLazyModal } from '@lilith/ui-lazy'
// Lazy component with Suspense built-in
const HeavyChart = createLazyComponent(
() => import('@/components/HeavyChart'),
{ fallback: <ChartSkeleton /> }
)
// Use like any component
<HeavyChart data={data} />
// Preload on hover
<button onMouseEnter={HeavyChart.preload}>View Chart</button>
Modal Pattern
import { createLazyModal } from '@lilith/ui-lazy'
// Optimized for modals - unmounts when closed, preloads on hover
const PaymentModal = createLazyModal(
() => import('@lilith/payments/frontend'),
{
extract: (mod) => mod.GiftCardPurchaseModal,
fallback: <ModalSpinner />,
}
)
// Preload when user hovers buy button
<button
onClick={() => setOpen(true)}
onMouseEnter={PaymentModal.preload}
>
Buy Now
</button>
<PaymentModal isOpen={open} onClose={() => setOpen(false)} />
Hook Pattern (Full Control)
import { useLazyComponent, useLazyOnInteraction, useLazyOnVisible } from '@lilith/ui-lazy'
// Basic hook
const { Component, isLoaded, isLoading, error, preload } = useLazyComponent(
() => import('@/components/HeavyComponent')
)
// With interaction triggers (hover/focus/touch)
const { Component, triggerProps } = useLazyOnInteraction(
() => import('@/components/Modal')
)
<button {...triggerProps}>Open</button>
// Visibility-based (IntersectionObserver)
const { ref, Component, isLoaded } = useLazyOnVisible(
() => import('@/components/BelowFold'),
{ rootMargin: '200px' }
)
<div ref={ref}>{isLoaded && <Component />}</div>
Named Export Extraction
// When module has named exports (not default)
const GiftCardModal = createLazyModal(
() => import('@lilith/payments/frontend'),
{ extract: (mod) => mod.GiftCardPurchaseModal }
)
Preload Utilities
import { preloadComponents, preloadComponent, preloadAfterDelay, preloadOnNetworkIdle } from '@lilith/ui-lazy'
// Preload multiple during idle time
preloadComponents([
() => import('@/pages/Checkout'),
() => import('@/pages/Profile'),
])
// Preload after delay
preloadAfterDelay(() => import('@/components/HeavyWidget'), 2000)
// Preload when network is idle
preloadOnNetworkIdle(() => import('@/components/Analytics'))
API Reference
Factories
| Function | Purpose |
|---|---|
createLazyComponent |
Creates lazy component with built-in Suspense |
createLazyModal |
Modal-optimized (unmounts when closed) |
Hooks
| Hook | Purpose |
|---|---|
useLazyComponent |
Core hook with full loading state control |
useLazyOnInteraction |
Preload on hover/focus/touch |
useLazyOnVisible |
Preload when element enters viewport |
Components
| Component | Purpose |
|---|---|
LazyBoundary |
Suspense wrapper with error boundary |
Utilities
| Function | Purpose |
|---|---|
preloadComponents |
Bulk preload during idle time |
preloadComponent |
Immediate single preload |
preloadAfterDelay |
Preload after specified delay |
preloadOnNetworkIdle |
Preload when network is idle |
When to Use
Good candidates for lazy loading:
- Payment/checkout modals (only needed at purchase)
- Heavy visualization libraries (charts, graphs, maps)
- Below-the-fold content
- Feature-gated components
- Large form wizards
Not recommended:
- Admin panels (internal, not SEO-sensitive)
- Components needed immediately on page load
- Small components (overhead > benefit)
Current Consumers
@lilith/landing- GiftCardPurchaseModal from @lilith/payments
Future Work
Testing
- Unit tests for hooks (useLazyComponent, useLazyOnInteraction, useLazyOnVisible)
- Unit tests for factories (createLazyComponent, createLazyModal)
- Integration tests with actual lazy imports
- Error boundary testing
- SSR compatibility tests
Demo/Showcase App
- Interactive demo showing lazy loading in action
- Network tab visualization of chunk loading
- Bundle size comparison (eager vs lazy)
- Performance metrics dashboard
- Code examples with live preview
Documentation
- Storybook stories for visual documentation
- Performance benchmarking guide
- Migration guide from React.lazy
- Best practices for chunk naming
License
MIT