Import on Visibility: Lazy Loading with IntersectionObserver
Learn the interview-ready mental model, practical trade-offs, and production patterns for this web fundamentals topic.
Topic content
Import on Visibility combines IntersectionObserver with dynamic import() to load JavaScript-heavy components only when they approach the user's viewport. This pattern further reduces initial bundle size for below-the-fold content while providing smooth perceived performance through rootMargin prefetching.
Static imports = cooking everything before opening the restaurant. Import on Interaction = cooking after they order. Import on Visibility = starting prep when you see them walking toward the table (via IntersectionObserver). You save resources on startup and still deliver smoothly when they arrive.
1IntersectionObserver Basics
The modern, efficient way to detect when an element enters the viewport without expensive scroll listeners. Use rootMargin to start loading slightly before the element is visible.
const observer = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
loadHeavyComponent();
observer.disconnect();
}
});
}, { rootMargin: '150px' });
observer.observe(placeholderElement);2Basic Implementation
Combine observer with dynamic import() to load and mount the real component only when needed.
3React Hook Pattern
Encapsulate logic into a reusable hook for clean, production-ready usage with proper cleanup and state management.
function useLoadOnVisibility(loader, rootMargin = '150px') {
const ref = useRef(null);
const [Component, setComponent] = useState(null);
// ... loading & error states
}4Reusable Component & Advanced Tips
Create <LazyLoadOnVisible /> wrapper. Support parallel imports, meaningful placeholders, error handling, and cleanup to prevent memory leaks.
- ✓IntersectionObserver + dynamic import() = efficient below-the-fold lazy loading
- ✓Use positive rootMargin to prefetch before visibility
- ✓Always disconnect observer and guard against duplicate loads
- ✓Best for comments, embeds, charts, recommendations — not core UI
- ✓Provide excellent placeholders and error handling for great UX
- ✓Combine with import on interaction for complete lazy loading coverage