Back
Web Fundamentals

Import on Interaction: Load When User Interacts

Web Fundamentals
Build & Deployment: Monorepo, CI/CD, Strategies & Release SafetyState Management: Choosing the Right SolutionRedux: Predictable State Container (RTK + RTK Query)React Query (TanStack Query): Server State CachingData Fetching Patterns: REST, GraphQL, tRPC & Real-timeGraphQL Fundamentals for Frontend: Shape, Caching, and TradeoffsgRPC-Web Fundamentals: Browser Constraints and Proxy ModelCaching Strategies: Client, Server & EdgeData Normalization: Organizing State for PerformanceAPI Design Best Practices: Pagination, Errors, Versioning & Type SafetyAPI Versioning Strategies for Frontend CompatibilityPagination: Offset vs Cursor-BasedRate Limiting & API Resilience: Retries, Backoff, Jitter, IdempotencyHow Frontend Developers Can Handle Millions of API Requests Without Crashing EverythingBrowser Storage: Cookies, SessionStorage, LocalStorage, IndexedDBReal-time Communication: WebSockets, SSE & PollingWebRTC: Real-Time Communication in the BrowserCore Web Vitals: LCP, INP & CLSPerformance Optimization Trade-offsCritical Resource Prioritization: Optimize Loading OrderCode Splitting: Optimize Bundle Size with Dynamic ImportsTree Shaking: Eliminate Dead Code from Your BundleLazy Loading: Load Resources On-DemandResource Hints: Preload, Prefetch & PreconnectText Compression: Gzip and BrotliImage & Video Optimization: Modern Formats & TechniquesAdaptive Loading: Optimize for Device & NetworkList Virtualization: Render Large Lists EfficientlyWeb Workers vs Main Thread: Offloading Heavy WorkMemory Leaks in Frontend Apps: Detection & PreventionManaging Third-Party Scripts: Optimization StrategiesHow CDNs Work: Edge Delivery, Caching & PerformanceHTTP Caching Deep Dive: Cache-Control, ETag & RevalidationService Workers & Offline Strategy: Cache First, Network First & Update LifecyclePWA Fundamentals: Manifest, Installability & Offline UXCritical Rendering PathScript Loading: async vs deferEvent Loop: Understanding JavaScript Execution ModelJavaScript Module Systems: CJS vs ESM vs UMDDynamic Module Loading: import() FunctionImport on Interaction: Load When User InteractsImport on Visibility: Lazy Loading with IntersectionObserverBrowser Rendering Pipeline & Layout ThrashingRendering Strategies: CSR vs SSR vs SSG vs ISRStreaming SSR: Progressive HTML StreamingIslands Architecture: Independent Component HydrationReact Server Components: Zero-JS Server RenderingFramework Reactivity: React, Vue, Svelte & SolidHTTP/1.1 vs HTTP/2 vs HTTP/3 (QUIC) for Frontend PerformanceDNS Resolution: Path, TTL, Caching & Frontend ImpactCross-Site Scripting (XSS) AttacksCross-Site Request Forgery (CSRF) AttacksCORS Explained: Cross-Origin Resource SharingCORS Preflight in Practice: Credentials, Simple Requests & MisconfigurationsContent Security Policy (CSP)Why is HTTPS Secure? Understanding TLS/SSLAuthorization Best PracticesCookie Security & Session Hardening: SameSite, HttpOnly, Secure
mediumRendering & Browser Architecture

Import on Interaction: Load When User Interacts

TL;DRTrigger dynamic import() on user actions (click/hover/focus) to load heavy optional features only when intent is shown
High Signal
Google
Meta
Agoda
Meesho
30-Second Answerstart every interview with this

Import on Interaction is a performance pattern that uses dynamic import() to load non-critical code only when the user explicitly interacts with a UI element. It reduces initial JavaScript bundle size while deferring cost to the moment of actual need. Combine with prefetching on hover/focus and Promise caching for smooth UX.

Static imports = pre-cooking everything before the restaurant opens. Import on Interaction = cooking expensive dishes only after the customer orders them. You save kitchen resources upfront, but the first order might take slightly longer unless you start prep on early signals like seeing the menu (hover/focus).

User Intent (Click / Hover / Focus)
dynamic import()
Fetch + Execute Chunk
Feature Ready (with loading UI)

1Basic Click Pattern

Load the module only when the user clicks. Cache the result so subsequent clicks are instant.

SettingsButton.jsxjsx
const handleOpen = async () => {
  if (!Modal) {
    const mod = await import('./SettingsModal');
    setModal(() => mod.default);
  }
  setOpen(true);
};

2Prefetch on Hover / Focus

Start loading on early intent signals (mouseenter, focus) to hide network latency before the actual click.

ChatTrigger.jsxjsx
<button 
  onMouseEnter={prefetch} 
  onFocus={prefetch} 
  onClick={handleClick}
>
  Open Chat
</button>

3Promise Caching

Cache the import Promise to avoid duplicate requests and simplify loading state management.

useLoadOnInteraction.jsjs
let modalPromise;
function loadModal() {
  if (!modalPromise) modalPromise = import('./Modal');
  return modalPromise;
}

4React Hook Pattern

Encapsulate loading, caching, states, and prefetching into a reusable hook for clean component code.

PropertyEager / Static ImportImport on Interaction
BehaviorLoaded during initial bundleLoaded only on user action
Use CaseCore features needed on first paintOptional, heavy, secondary features
Bundle ImpactIncreases initial JS sizeSmaller initial bundle
Interaction LatencyZero (already loaded)Small delay on first use

Eager / Static Import

Behavior

Loaded during initial bundle

Use Case

Core features needed on first paint

Bundle Impact

Increases initial JS size

Interaction Latency

Zero (already loaded)

Import on Interaction

Behavior

Loaded only on user action

Use Case

Optional, heavy, secondary features

Bundle Impact

Smaller initial bundle

Interaction Latency

Small delay on first use

Common questions

  • ›“How would you implement lazy loading on user interaction?”
  • ›“What is the difference between lazy loading on mount vs on interaction?”
  • ›“How do you reduce perceived latency when using import on interaction?”
  • ›“When is this pattern a good idea vs a bad idea?”

What interviewers look for

  • Clear distinction between lazy-on-mount and true intent-driven loading
  • Understanding of Promise caching and prefetch strategies
  • Awareness of UX tradeoffs and loading states
  • Realistic candidate selection (good vs bad features)

Short answer (60 sec)

Import on interaction triggers dynamic import() on explicit user actions like clicks. It reduces initial bundle size by moving non-critical code off the startup path while using hover/focus prefetching and Promise caching to minimize first-use delay.

Detailed answer (senior level)

This pattern builds on dynamic import() to create intent-driven code splitting. Load on click for safety, prefetch on hover/focus for better responsiveness, and always cache the Promise. Good candidates are heavy optional features (modals, editors, charts). The main tradeoff is moving cost from startup to first interaction — manage it with loading UI, error handling, and careful feature selection. Senior answers include reusable hooks and performance measurement.

  • Loading on mount (useEffect) instead of real user interaction
  • No loading states or feedback on first click
  • Not caching the Promise → duplicate network requests
  • Deferring critical path or tiny modules
  • Ignoring mobile (no hover) and error handling
Key Takeaways
  • ✓Import on interaction defers heavy optional code until explicit user intent
  • ✓Combine click loading with hover/focus prefetching for smoother UX
  • ✓Always cache the import Promise to avoid redundant work
  • ✓Provide clear loading and error states
  • ✓Best for modals, editors, charts, admin tools — not core navigation
  • ✓Measure both initial bundle reduction and interaction-to-ready latency
Previous TopicDynamic Module Loading: import() FunctionNext Topic Import on Visibility: Lazy Loading with IntersectionObserver

On this page