Skip to main content
Code splitting breaks your application into smaller chunks that are loaded on demand, reducing initial bundle size and improving load times.

Lazy routes

Split route components using createLazyRoute:
src/routes/posts/$postId.tsx
src/routes/posts/$postId.lazy.tsx

Code-based lazy routes

For code-based routing:
src/routes/posts.lazy.tsx

Lazy route components

Lazy-load just the component:
src/routes/Dashboard.tsx

What to split

Critical loader logic

Keep loaders in the main bundle for SSR:

Heavy components

Split large component libraries:

Route groups

Split entire route sections:

Preloading strategies

Control when chunks are loaded:

Manual preloading

Preload routes programmatically:

Suspense boundaries

Control loading states during code splitting:

Pending components

Show loading state while lazy chunks load:

Bundle analysis

Analyze bundle sizes to find optimization opportunities:
vite.config.ts

Route-level splitting

Ensure each route is in its own chunk:
vite.config.ts

Dynamic imports

Lazy-load utilities and helpers:

Best practices

Loaders should not be lazy-loaded - they need to run on the server.
Each route should be its own chunk for optimal caching.
Use preload=“intent” or preload=“viewport” for frequently accessed routes.
Wrap lazy routes in Suspense to show loading states.
Regularly check bundle sizes and split large chunks.

Performance tips

Target bundle size: Aim for chunks under 200KB. Larger chunks should be split further.
Prefetch on idle: Use requestIdleCallback to preload routes during browser idle time.
Over-splitting can hurt performance. Balance chunk count with chunk size.

Next steps

File-based routing

Learn automatic route splitting

Vite plugin

Configure code splitting