Advanced

Build Optimization

Optimizing production builds with code splitting, chunking, and bundle analysis.

Build Optimization

TL;DR

Learn how to optimize production builds for smaller bundles, faster loading, and better performance using Manic's built-in optimization features.

What It Is

Build optimization in Manic involves:

OptimizationPurposeImpact
Code SplittingSplit routes into separate chunksFaster initial load
Tree ShakingRemove unused codeSmaller bundles
MinificationCompress outputFaster downloads
ChunkingSplit large dependenciesParallel loading

Prerequisites


Quick Start

Default Optimization

Manic includes optimization by default:

// manic.config.ts
export default defineConfig({
  build: {
    // Default: true (minify in production)
    minify: true,
    // Default: true (generate sourcemaps)
    sourcemap: false,  // Disable for smaller output
  },
});

How It Works

Build Pipeline with Optimization

Initializing diagram...

Code Splitting

How Manic Splits Code

By default, each route becomes a separate chunk:

index.js

Manual Code Splitting

Use dynamic imports for lazy loading:

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

// Usage with Suspense
<React.Suspense fallback={<ChartSkeleton />}>
  <HeavyChart data={data} />
</React.Suspense>

Optimization Options

Configure in manic.config.ts

// manic.config.ts
export default defineConfig({
  build: {
    // Minify JavaScript (default: true in production)
    minify: true,
    
    // Generate source maps (default: false in production)
    sourcemap: false,
    
    // Target browser versions
    target: 'es2022',
    
    // Split chunks
    splitting: true,
    chunking: true,
  },
});

Bundle Analysis

Analyze Bundle Size

# Build with analysis
bun build --analyze

# View in browser
# Open dist/client/ and check file sizes

Tools

ToolPurpose
Chrome DevToolsNetwork tab for load times
Bundle AnalyzerVisual chunk map
LighthousePerformance audit

Examples

Example 1: Lazy Load Routes

// Using Link - automatic lazy loading
import { Link } from 'manicjs';

// This route chunk loads only when user clicks
<a href="/reports/2024">View Report</a>

Example 2: Prefetch Optimization

// Prefetch on hover (default behavior)
<a href="/about" prefetch="hover">About</a>

// Don't prefetch for slower connections
<a href="/large-page" prefetch={false}>Large Page</a>

Example 3: Dynamic Imports

// Explicit lazy loading
const Modal = React.lazy(() => import('./Modal'));

function App() {
  const [showModal, setShowModal] = useState(false);
  
  return (
    <>
      <button onClick={() => setShowModal(true)}>
        Open Modal
      </button>
      
      {showModal && (
        <React.Suspense fallback={<ModalSkeleton />}>
          <Modal onClose={() => setShowModal(false)} />
        </React.Suspense>
      )}
    </>
  );
}

Common Issues

Issue 1: Large Bundle Size

Solution:

  1. Check for unused imports
  2. Enable tree shaking
  3. Lazy load heavy components
# Analyze bundle
bun build --analyze

Issue 2: Slow Build

Solution:

// Only rebuild changed files in dev
// Ensure watching is enabled

Issue 3: Chunk Loading Issues

Solution: Check dynamic import paths:

// ✗ BAD
const Heavy = import('./HeavyComponent');  // No await

// ✓ GOOD
const Heavy = import('./HeavyComponent').then(m => m.default);

Best Practices

Use route-based splitting for optimal chunks.

Don't manually split too aggressively; let Manic handle the heavy lifting.

Monitor bundle size over time.


Performance Checklist

  • Enable minification in production
  • Use route-based splitting
  • Lazy load heavy components
  • Monitor bundle sizes
  • Test with Lighthouse

See also:

On this page