
What code splitting is
Code splitting breaks one giant JavaScript bundle into smaller chunks that load only when they are actually needed, by route, by component, or on interaction, instead of shipping your entire app to every visitor up front. It is the main lever for cutting the JavaScript that render-blocks and clogs the main thread.
Why it matters: every kilobyte of JS has to be downloaded, parsed, compiled, and executed on the main thread. A 500KB bundle that only needs 80KB for the landing page means the browser is choking on code the user will never trigger. That shows up as high Total Blocking Time in the lab and poor INP in the field, both symptoms of a busy main thread.
Real code splitting: dynamic import()
The core primitive is the dynamic import(), which returns a promise and tells the bundler to peel that module into its own chunk. You load heavy, rarely-used code only at the moment it is needed.
// BEFORE: the chart library ships in the main bundle for everyone,
// even visitors who never open the dashboard.
import { renderChart } from './heavy-charting-lib';
renderChart(data);
// AFTER: split it out, load it only when the dashboard tab is clicked.
document.querySelector('#dashboard-tab').addEventListener('click', async () => {
const { renderChart } = await import('./heavy-charting-lib');
renderChart(data);
});In a framework the same idea is expressed with lazy component loading:
// React: route-level split, each route is its own chunk
import { lazy, Suspense } from 'react';
const Dashboard = lazy(() => import('./routes/Dashboard'));
<Suspense fallback={<Spinner />}>
<Dashboard />
</Suspense>The two natural seams are route-based (each page loads only its own code) and component-based (a modal, chart, or editor loads only when opened). Route-based splitting is the highest-leverage place to start.
Splitting strategies compared
| Strategy | What loads when | Best for | Watch out for |
|---|---|---|---|
| Route-based | Each route's code loads on navigation to it | Multi-page apps, the default first move | Shared deps duplicated if not extracted to a common chunk |
| Component-based | Heavy component loads when rendered/opened | Modals, charts, rich editors, maps | A visible loading flash if the chunk is large |
| On-interaction | Code loads on click/hover/scroll | Below-the-fold widgets, third-party embeds | Slight delay on first interaction, prefetch to hide it |
| Vendor splitting | Framework/library code in its own long-cached chunk | Caching stable dependencies across deploys | Too many tiny vendor chunks add request overhead |
How to check it on your own site
- Open DevTools, Coverage tab, reload the landing page. If a large share of your JS is "unused," that code is a candidate to split out. Cross-reference the JavaScript for SEO checklist.
- Run Lighthouse and read the "Reduce unused JavaScript" and "Reduce JavaScript execution time" audits, and check Total Blocking Time. High numbers point straight at an oversized bundle.
- In the Network tab, filter to JS and reload. One massive
main.jswith no route chunks means you are not splitting. Healthy apps show a small entry chunk plus per-route chunks that appear as you navigate. - Use your bundler's analyzer (webpack-bundle-analyzer, Vite's rollup visualizer) to see what dominates the bundle, that big treemap block is usually your first split target.
- Test with a mid-range mobile CPU throttle (4x) and watch how long the main thread is blocked during load. That is what real INP feels like.
Common mistakes and how to fix them
- Splitting into too many tiny chunks. Each chunk is a separate request with its own overhead. Over-splitting can be slower than one bundle. Split at meaningful seams (routes, heavy components), not every file.
- No prefetch on likely-next chunks. If clicking a tab triggers a cold download, the user waits. Prefetch the chunk on hover or when the link enters the viewport so it is ready on click.
- Duplicated dependencies across chunks. Without a shared/common chunk, the same library gets bundled into several routes. Configure a shared chunk so common code is downloaded once.
- Splitting content Google needs to see. If critical, indexable content only appears after a lazy chunk executes, rendering and indexing can suffer. Keep primary content in the server-rendered HTML, split enhancements, not core content. See the JavaScript SEO FAQ.
- No loading fallback. A lazy component with no
Suspensefallback flashes blank or errors. Always provide a fallback UI.
FAQ
Does code splitting help Core Web Vitals?
Yes, mainly TBT in the lab and INP in the field. Shipping less JavaScript up front means less main-thread work blocking user input, which is exactly what INP measures. It can also help LCP by freeing bandwidth and CPU for the content that matters.
Will code splitting hurt my SEO if Google can't run the chunks?
It can, if you split content Google needs to index. Googlebot does render JavaScript, but relying on lazy chunks for primary content adds risk and delay. Keep core content in the initial HTML and split the interactive extras.
What is the difference between code splitting and tree shaking?
Tree shaking deletes code you never use at build time. Code splitting keeps code you do use but defers loading it until it is needed. They are complementary, shake out dead code, then split what remains by when it is required.
Where should I start splitting?
Routes first. Route-based splitting gives the biggest win for the least effort, each page stops paying for other pages' code. After that, split the heaviest single components: charts, editors, maps, video players.
How is code splitting different from render-blocking scripts?
Render-blocking is about when a script runs relative to the first paint. Code splitting is about how much script you ship at all. You want both: defer or async your scripts so they do not block render, and split them so the bundle is small in the first place.
Claude Vincent is a technical SEO consultant focused on crawlability, rendering, and AI-search visibility. He writes the field guides and case studies at SEO ProCheck, with a bias toward the durable, unglamorous work that decides whether search engines and AI answer engines can actually read and cite a site.
About SEO ProCheck
Technical SEO consulting and GEO strategy with 20 years of enterprise experience. Case studies, resources, and tools for search and AI visibility.
Work With Me
Technical SEO audits, GEO strategy, site migrations, and international SEO. Hourly consulting for teams who need hands-on support, not just reports.







