Skip to main content

Code splitting implemented at route level

ab-002023 · performance-deep-dive.bundle-analysis.code-splitting-routes
Severity: highactive

Why it matters

Without route-level code splitting, your admin dashboard, settings page, and checkout flow all ship to users who visit only your landing page. A monolithic bundle forces every visitor to download and parse code for routes they will never reach in that session. ISO 25010:2011 time-behaviour flags the slowdown; the practical result is a Time to Interactive that scales with your total codebase size rather than the complexity of the current page.

Severity rationale

High because a single monolithic bundle forces every user to download and parse code for all routes simultaneously, making Time to Interactive proportional to total app size rather than the page being visited.

Remediation

In Next.js App Router, each file in app/ already produces a separate chunk automatically. For client components or shared heavy components that are route-specific, use next/dynamic.

// app/admin/reports/page.tsx — heavy report component split off
import dynamic from 'next/dynamic'
const ReportChart = dynamic(() => import('@/components/report-chart'), { loading: () => <Skeleton /> })

Verify route splitting worked by checking .next/static/chunks/ — you should see per-route files, not a single app.js.

Detection

  • ID: performance-deep-dive.bundle-analysis.code-splitting-routes

  • Severity: high

  • What to look for: Count all routes/pages in the application. Enumerate how many produce separate JavaScript chunks in the build output vs. sharing a monolithic bundle. Examine the page/route structure and how code is imported. Look for dynamic imports using React.lazy, import(), or framework equivalents (Next.js dynamic imports, SvelteKit preload). Check the build output to confirm separate chunks exist for different routes.

  • Pass criteria: Each route loads only its own code via code splitting. The build output shows separate .js chunks per route. Admin pages, settings, or heavy feature routes are not included in the initial bundle. At least 90% of routes should have separate chunks.

  • Fail criteria: All route code is bundled together. A single monolithic .js bundle contains code for every page, even pages the user never visits.

  • Skip (N/A) when: Never — route-level code splitting is a best practice for all multi-route applications.

  • Cross-reference: For dynamic imports of heavy UI components within routes, see the dynamic-imports-heavy-ui check.

  • Detail on fail: "All route code bundled into single main.js (1.2MB gzipped). No per-route chunks detected in build output" or "Settings and admin routes included in initial bundle despite being gated behind authentication"

  • Remediation: Implement route-level code splitting so each route loads only its dependencies. In React, wrap route components with React.lazy() and Suspense. In Next.js, use dynamic imports for pages and components.

    // app/admin/page.tsx — Next.js App Router auto-splits per route
    // For manual splitting: const AdminPage = React.lazy(() => import('./AdminPage'))
    

External references

Taxons

History