Volume 4

Q197: Code Splitting, Prefetching and Loading Strategy

Difficulty: SeniorFrequency: HighAnswer time: 8-12 minutes

What Interviewers Want To Evaluate

This question checks whether you can load code at the right time. Interviewers want route splitting, component splitting, dynamic imports, prefetching, preload, Suspense, loading states, network priority, cache behavior, and avoiding both over-eager and too-late loading.

Senior answers should describe strategy by user intent.

Short Interview Answer

Code splitting breaks JavaScript into chunks so users do not download every feature up front. Prefetching loads likely future code at lower priority, while preloading loads critical current resources earlier. Good loading strategy follows user intent: load current-route essentials immediately, prefetch likely next routes or interactions, dynamically import heavy rare features, and show stable loading UI for anything that can wait.

Detailed Interview Answer

Loading strategy has a simple goal:

load what the user needs now
prepare what the user is likely to need next
delay what the user may never use

This is more useful than splitting randomly.

Route Splitting

Most modern frameworks split by route.

That means /practice/javascript should not necessarily ship the same code as /questions/[slug].

Route splitting is the first level of protection.

But route splitting alone may not be enough when one route contains several heavy optional features.

Component Splitting

Component-level dynamic import is useful for heavy delayed features.

Examples:

rich code editor
chart library
map
video player
PDF viewer
admin report
large syntax highlighter
rare settings panel

Do not split tiny components just to split them. Every chunk has overhead.

Dynamic Import Example

const HeavyEditor = lazy(() => import("./HeavyEditor"));

function PracticePage() {
  return (
    <Suspense fallback={<EditorSkeleton />}>
      <HeavyEditor />
    </Suspense>
  );
}

The loading boundary should match the delayed feature.

Prefetching

Prefetching loads likely future resources before the user asks.

Good candidates:

next route linked in viewport
next step in wizard
details page after hover
practice console after user opens practice section
latest question after homepage load

Prefetching should not compete with critical current-page work.

Preloading

Preload is for resources needed for the current page soon.

Examples:

LCP image
critical font
critical CSS
important route chunk in a known transition

Preloading too much can hurt performance by stealing bandwidth from truly critical resources.

Suspense and Loading UI

Code-split UI needs good fallback design.

Good fallback:

matches final size
keeps stable shell visible
does not shift layout
explains pending state when needed
does not block unrelated UI

Bad fallback makes code splitting feel broken.

Cache Behavior

Chunks should be cacheable.

Hashed filenames let browsers reuse unchanged chunks across deployments.

But frequent changes to shared chunks can reduce cache value.

Review:

vendor chunk stability
shared component churn
route-specific chunk ownership
long-term caching headers
deployment invalidation behavior

Over-Splitting

Too many chunks can hurt.

Costs:

extra requests
waterfalls
more coordination
late loading gaps
harder debugging
cache fragmentation

Split meaningful heavy boundaries, not every file.

Under-Splitting

Under-splitting ships too much up front.

Signs:

large initial JS
unused route features loaded immediately
heavy libraries on simple pages
slow hydration
poor mobile startup

Bundle analysis reveals this.

Common Mistakes

A common mistake is dynamically importing the LCP content.

Another mistake is preloading too many resources.

Another mistake is adding lazy boundaries with poor skeletons.

Another mistake is ignoring hover or viewport prefetch opportunities.

Another mistake is splitting without measuring the waterfall.

Senior Trade-Offs

Loading strategy balances startup speed and later interaction smoothness.

The right answer depends on user behavior.

Measure current route cost and next-action likelihood before choosing eager, prefetch, or lazy loading.

Debugging Workflow

When loading feels slow:

inspect network waterfall
identify critical resources
check chunk sizes
check lazy chunk timing
check prefetch behavior
check Suspense fallback
verify cache headers
remove over-eager code
preload only critical resources
measure field impact

Interview Framing

Define splitting, prefetching, and preloading. Then explain current need, likely next need, delayed features, Suspense fallback, and trade-offs.

Revision Notes

Loading strategy should follow user intent and resource priority.

Key Takeaways

Split by meaningful user paths, not arbitrary component boundaries.

Follow-Up Questions

  1. What is code splitting?
  2. How is prefetch different from preload?
  3. When should dynamic imports be used?
  4. Why not dynamically import LCP content?
  5. What makes a good loading fallback?
  6. What is over-splitting?
  7. What is under-splitting?
  8. How do cache headers matter?
  9. How does route behavior guide prefetching?
  10. How do you inspect loading waterfalls?

How I Would Answer This In A Real Interview

I would say I load current-route essentials immediately, prefetch likely next interactions, and dynamically import heavy rare features with stable Suspense fallbacks. I would validate the strategy with bundle analysis, network waterfalls, cache behavior, and field metrics.