In short
Not every user opens the PDF export or the fancy chart. Code splitting lets you load that code only when someone actually needs it, keeping the first load light.
The broader practice — of which bundle/route splitting are techniques — of dividing your app's code into smaller pieces loaded only when needed.

Think of it like this
The chaiwala's back stock
The chai stall keeps tea, sugar and milk on the counter. Bun maska supplies sit in the back and come out only when someone orders. Your main bundle is the counter. Rarely used features stay in the back until asked for.
Watch it happen
Clicking Show chart
GET main.js
1/6The page loads with the main bundle. MarksChart and jsPDF aren't in it.
The big ideas
What you need to know
import() makes a split point
A dynamic import() tells the bundler to put that module in its own chunk, loaded when the line runs.
React.lazy for components
lazy(() => import("./Chart")) plus Suspense shows a fallback while the component's code downloads.
Routes split automatically
Next.js and most modern routers already give each page its own chunk. You split the heavy parts inside pages.
See it in code
Walk through the code
1import { lazy, Suspense, useState } from "react";2const MarksChart = lazy(() => import("./MarksChart"));3 4export function Report() {5 const [showChart, setShowChart] = useState(false);6 async function downloadPdf() {7 const { jsPDF } = await import("jspdf"); // loaded only on click8 new jsPDF().text("Semester report", 10, 10).save("report.pdf");9 }10 return (11 <>12 <button onClick={() => setShowChart(true)}>Show chart</button>13 <button onClick={downloadPdf}>Download PDF</button>14 {showChart && <Suspense fallback={<p>Loading chart…</p>}><MarksChart /></Suspense>}15 </>16 );17}1/3lazy plus a dynamic import puts MarksChart in its own chunk.
Neither the chart library nor jsPDF is in the first download. In Next.js, next/dynamic does the same job as React.lazy.
Save yourself the pain
Common mistakes
Oops
Lazy loading the main content of the page.
Do this instead
Split what's below the fold or behind a click. Lazy loading what users see first just adds a spinner.
Oops
Using React.lazy without a Suspense boundary.
Do this instead
Wrap lazy components in Suspense with a fallback, or React will throw while the chunk loads.
Your mission
Move a heavy library off the first load
Quick check
What does const Chart = lazy(() => import("./Chart")) change about your bundle?
Go deeper
- 1Identify 2-3 natural split points in an app (routes, modals, heavy widgets).
- 2Compare initial bundle size before and after splitting them out.
- 3Learn the difference between route-based and component-based code splitting.
More topics at this stop
Stuck on this topic? Ask an Insider
Get 1:1 guidance from people who've walked this exact path — on the InsideEdge app.