Lesson 9 of 30
Without code splitting, every visitor downloads 100% of your app's JavaScript on the very first visit, including code for pages and features they may never touch.
12 min read
Every option explains itself — why the right one is right, and why each wrong one is wrong. Miss one and it comes back later on a spaced-repetition schedule.
Question 1 of 3
An app ships a single JavaScript bundle containing every route's code, including an admin dashboard almost no visitors ever open. What problem does route-based code splitting solve here?
Hints without spoilers, and a plain explanation of why a wrong answer was wrong — answered only from this lesson. Free account, no card.
Sign up freeWhat interviewers actually ask about this, and what a strong answer has to cover.
A strong answer covers
Likely follow-ups
A single bundle means a single download: every route, every rarely-used feature, every heavy dependency ships to every visitor before the first page can even become interactive, regardless of which page they actually landed on. Code splitting breaks that single bundle into multiple chunks that load on demand, using dynamic import() instead of a static import at the top of the file:
Both reduce the amount of JavaScript that has to be downloaded, parsed, compiled, and executed before the page is interactive on first load — the same JS-cost problem the bundling/tree-shaking lesson addresses from the "remove code nobody imports" angle; this is the complementary "defer code that IS used, just not yet" angle.
// Route-based: this route's whole subtree loads only when visited
const SettingsPage = lazy(() => import("./routes/SettingsPage"));
// Component-level: only loads once the user actually opens the editor
function DocumentEditor() {
const [showRichText, setShowRichText] = useState(false);
const RichTextEditor = lazy(() => import("./RichTextEditor"));
return (
<div>
<button onClick={() => setShowRichText(true)}>Edit</button>
{showRichText && (
<Suspense fallback={<EditorSkeleton />}>
<RichTextEditor />
</Suspense>
)}
</div>
);
}
Neither SettingsPage nor RichTextEditor's code is in the initial bundle. The browser only requests them, as separate chunks, the moment they're actually needed — a visitor who never opens the editor never pays for its JavaScript at all.
RichTextEditor above were rendered immediately instead of behind a user action, splitting it would just add a second network round-trip in the critical path for something the browser needed right away.Suspense fallback for a lazily-loaded chunk is part of the user experience, not an afterthought — a component that pops in abruptly, or a blank gap with no fallback, is a rough edge users notice even when the underlying performance win is real."The initial bundle is huge and most users never touch half the app — how would you fix that?" is a real, common question, and naming route-based and component-level splitting as distinct techniques, plus being honest about the granularity tradeoff, is what separates a real answer from "just add lazy loading everywhere."