SalakCode SalakCode
Performance

Code Splitting

Load code on demand to improve performance

Intermediate
performance bundling webpack lazy-loading

Definition

Code splitting is the practice of splitting your JavaScript bundle into smaller chunks that can be loaded on demand. This reduces the initial bundle size, improving Time to Interactive (TTI) and overall performance.

Dynamic Imports

Basic Syntax

// Instead of static import
import { add } from './math';
console.log(add(2, 3));

// Use dynamic import
import('./math').then(math => {
  console.log(math.add(2, 3));
});

// With async/await
async function loadMath() {
  const math = await import('./math');
  return math.add(2, 3);
}

Conditional Loading

async function loadFeature(featureName) {
  if (featureName === 'chart') {
    const { Chart } = await import('./Chart');
    return Chart;
  }
  
  if (featureName === 'map') {
    const { Map } = await import('./Map');
    return Map;
  }
}

React.lazy and Suspense

Route-Based Splitting

import { lazy, Suspense } from 'react';
import { BrowserRouter, Routes, Route } from 'react-router-dom';

// Lazy load route components
const Home = lazy(() => import('./routes/Home'));
const About = lazy(() => import('./routes/About'));
const Dashboard = lazy(() => import('./routes/Dashboard'));

function App() {
  return (
    <BrowserRouter>
      <Suspense fallback={<div>Loading...</div>}>
        <Routes>
          <Route path="/" element={<Home />} />
          <Route path="/about" element={<About />} />
          <Route path="/dashboard" element={<Dashboard />} />
        </Routes>
      </Suspense>
    </BrowserRouter>
  );
}

Component-Level Splitting

import { lazy, Suspense, useState } from 'react';

// Lazy load heavy component
const HeavyChart = lazy(() => import('./HeavyChart'));

function Dashboard() {
  const [showChart, setShowChart] = useState(false);
  
  return (
    <div>
      <button onClick={() => setShowChart(true)}>
        Show Chart
      </button>
      
      {showChart && (
        <Suspense fallback={<div>Loading chart...</div>}>
          <HeavyChart />
        </Suspense>
      )}
    </div>
  );
}

Named Exports

Wrapping Named Exports

// math.js
export const add = (a, b) => a + b;
export const subtract = (a, b) => a - b;

// Component wrapper for default export
export const MathOperations = {
  add,
  subtract
};

// Lazy import with named exports
const LazyMath = lazy(() => import('./math').then(module => ({
  default: module.MathOperations
})));

Preloading Strategies

Prefetch on Hover

function LinkWithPrefetch({ to, children }) {
  const handleMouseEnter = () => {
    // Prefetch route on hover
    const About = import('./routes/About');
  };
  
  return (
    <a 
      href={to} 
      onMouseEnter={handleMouseEnter}
    >
      {children}
    </a>
  );
}

Webpack Magic Comments

// Prefetch chunk
const Admin = lazy(() => import(
  /* webpackChunkName: "admin" */
  /* webpackPrefetch: true */
  './Admin'
));

// Preload chunk (higher priority)
const Dashboard = lazy(() => import(
  /* webpackChunkName: "dashboard" */
  /* webpackPreload: true */
  './Dashboard'
));

Bundle Analysis

// webpack-bundle-analyzer
// Install: npm install --save-dev webpack-bundle-analyzer

// webpack.config.js
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;

module.exports = {
  plugins: [
    new BundleAnalyzerPlugin()
  ]
};

Best Practices

Split by Route

// Each major route gets its own chunk
const routes = [
  {
    path: '/',
    component: lazy(() => import('./Home'))
  },
  {
    path: '/products',
    component: lazy(() => import('./Products'))
  },
  {
    path: '/cart',
    component: lazy(() => import('./Cart'))
  }
];

Split Large Libraries

// Load heavy libraries only when needed
async function generatePDF() {
  const { jsPDF } = await import('jspdf');
  const doc = new jsPDF();
  doc.text('Hello World', 10, 10);
  doc.save('document.pdf');
}
Key Takeaway

Code splitting improves performance by loading JavaScript on demand. Use dynamic imports for route-based and component-level splitting, wrap lazy components with Suspense, and preload strategically. Analyze your bundle regularly to identify splitting opportunities.

Resources

Related Topics