bundle-optimizer

joshtol's avatarfrom joshtol

Analyze and reduce bundle size, implement code splitting, optimize dependencies, and improve build performance. Use when bundle is too large, load times are slow, or implementing progressive loading.

⭐10stars🔀1forks📁View on GitHub🕐Updated Nov 21, 2025

When & Why to Use This Skill

The Bundle Optimizer is a specialized Claude skill designed to enhance web performance by analyzing and reducing JavaScript bundle sizes. It provides expert guidance on implementing code splitting, tree-shaking, and dependency optimization. By leveraging advanced build configurations and diagnostic tools, it helps developers minimize load times, improve Core Web Vitals, and maintain efficient, high-performance web applications.

Use Cases

  • Scenario 1: Diagnosing and fixing slow initial page loads by identifying bloated dependencies and large modules using visual analysis tools.
  • Scenario 2: Implementing progressive loading and dynamic imports to ensure only essential code is delivered during the first paint.
  • Scenario 3: Optimizing build tool configurations (like Rollup, Webpack, or Next.js) for maximum minification and effective dead-code elimination (tree-shaking).
  • Scenario 4: Auditing and removing unused or duplicate npm packages to streamline the project's dependency graph.
  • Scenario 5: Integrating automated bundle size monitoring into CI/CD pipelines to prevent performance regressions during the development lifecycle.
namebundle-optimizer

Bundle Optimizer

You are an expert in optimizing JavaScript bundle sizes and build performance for the emotive-mascot platform.

When to Use This Skill

  • Bundle size exceeds targets (> 250 KB gzipped)
  • Slow initial page load times
  • Implementing code splitting
  • Analyzing dependency composition
  • Tree-shaking optimization
  • Progressive loading implementation

Current Bundle Targets

{
    "emotive-mascot.umd.js": {
        "uncompressed": "< 900 KB",
        "gzipped": "< 234 KB"
    },
    "emotive-mascot.minimal.js": {
        "uncompressed": "< 400 KB",
        "gzipped": "< 120 KB"
    },
    "emotive-mascot.audio.js": {
        "uncompressed": "< 700 KB",
        "gzipped": "< 200 KB"
    }
}

Analysis Tools

Check Current Size

# Build and check sizes
npm run build

# View bundle sizes
ls -lh dist/

# Check gzipped sizes
gzip -c dist/emotive-mascot.umd.js | wc -c

Analyze Bundle Composition

# Generate visual analysis
npm run build:analyze

# This creates bundle-analysis.html showing:
# - Module sizes
# - Duplicate dependencies
# - Large imports

NPM Package Analysis

# Audit dependencies
npm audit

# Check for unused dependencies
npx depcheck

# Analyze package sizes
npx bundle-phobia <package-name>

Optimization Techniques

1. Code Splitting

Split large features into separate chunks:

// Instead of direct import
import { AudioEngine } from '@joshtol/emotive-engine';

// Use dynamic import
const loadAudio = async () => {
    const { AudioEngine } = await import('@joshtol/emotive-engine/audio');
    return new AudioEngine();
};

2. Tree Shaking

Ensure dead code elimination works:

// rollup.config.js
export default {
    treeshake: {
        moduleSideEffects: false,
        propertyReadSideEffects: false,
        unknownGlobalSideEffects: false,
    },
};

// Use named imports (not default)
import { EmotiveMascot, emotions } from '@joshtol/emotive-engine';
// NOT: import EmotiveEngine from '@joshtol/emotive-engine'

3. Minification

Optimize Terser settings:

// rollup.config.js
import terser from '@rollup/plugin-terser';

terser({
    compress: {
        drop_console: true,
        drop_debugger: true,
        pure_funcs: ['console.log', 'console.debug'],
        passes: 2, // Multiple passes for better compression
    },
    mangle: {
        properties: {
            regex: /^_/, // Mangle private properties starting with _
        },
    },
    format: {
        comments: false, // Remove all comments
    },
});

4. Remove Unused Dependencies

# Find what can be removed
npx depcheck

# Uninstall unused packages
npm uninstall <package-name>

Progressive Loading Strategy

Minimal Initial Bundle

Create a minimal bundle for fast first paint:

// emotive-mascot.minimal.js includes ONLY:
// - Core engine
// - Basic emotions (5 most common)
// - Essential physics
// Total: ~120 KB gzipped

Lazy Load Features

Load features as needed:

// Load full emotion set on demand
const loadFullEmotions = async () => {
    const { extendedEmotions } = await import(
        '@joshtol/emotive-engine/emotions/extended'
    );
    mascot.addEmotions(extendedEmotions);
};

// Load audio module only when needed
const enableAudio = async () => {
    const { AudioEngine } = await import('@joshtol/emotive-engine/audio');
    mascot.enableAudio(new AudioEngine());
};

// Load LLM plugin for chat features
const enableChat = async () => {
    const { LLMEmotionPlugin } = await import(
        '@joshtol/emotive-engine/plugins/llm'
    );
    mascot.addPlugin(new LLMEmotionPlugin());
};

Build Configuration

Rollup Config Optimization

// rollup.config.js
import resolve from '@rollup/plugin-node-resolve';
import commonjs from '@rollup/plugin-commonjs';
import terser from '@rollup/plugin-terser';

export default {
    input: 'src/index.js',
    output: {
        file: 'dist/emotive-mascot.umd.js',
        format: 'umd',
        name: 'EmotiveMascot',
        sourcemap: false, // Disable in production
    },
    plugins: [
        resolve({
            browser: true,
            preferBuiltins: false,
        }),
        commonjs(),
        terser({
            compress: {
                drop_console: true,
                passes: 2,
            },
        }),
    ],
    treeshake: {
        moduleSideEffects: false,
    },
};

Next.js Config Optimization

// next.config.js
module.exports = {
    swcMinify: true, // Use SWC for faster minification

    webpack: (config, { isServer }) => {
        if (!isServer) {
            // Bundle analyzer
            if (process.env.ANALYZE === 'true') {
                const {
                    BundleAnalyzerPlugin,
                } = require('webpack-bundle-analyzer');
                config.plugins.push(
                    new BundleAnalyzerPlugin({
                        analyzerMode: 'static',
                        openAnalyzer: true,
                    })
                );
            }

            // Optimize chunks
            config.optimization.splitChunks = {
                chunks: 'all',
                cacheGroups: {
                    default: false,
                    vendors: false,
                    // Separate emotive-mascot into its own chunk
                    emotive: {
                        name: 'emotive-mascot',
                        test: /[\\/]node_modules[\\/]@joshtol[\\/]emotive-engine/,
                        priority: 40,
                    },
                },
            };
        }

        return config;
    },
};

Monitoring Bundle Size

Package.json Configuration

{
    "bundlesize": [
        {
            "path": "./dist/emotive-mascot.umd.js",
            "maxSize": "900 KB",
            "compression": "none"
        },
        {
            "path": "./dist/emotive-mascot.umd.js",
            "maxSize": "250 KB",
            "compression": "gzip"
        }
    ],
    "scripts": {
        "size": "bundlesize",
        "build:check": "npm run build && npm run size"
    }
}

CI/CD Integration

# .github/workflows/bundle-size.yml
name: Bundle Size Check

on: [pull_request]

jobs:
    check-size:
        runs-on: ubuntu-latest
        steps:
            - uses: actions/checkout@v2
            - run: npm ci
            - run: npm run build
            - run: npm run size

Quick Wins Checklist

  • Remove unused dependencies (run npx depcheck)
  • Enable tree-shaking in build config
  • Use terser with aggressive settings
  • Remove console.logs in production
  • Disable sourcemaps in production
  • Use dynamic imports for large features
  • Compress images and assets
  • Remove duplicate dependencies
  • Use minimal build for simple use cases
  • Monitor bundle size in CI/CD

Common Issues

Issue: Bundle size suddenly increased Solution: Run npm run build:analyze to identify what changed

Issue: Tree-shaking not working Solution: Ensure all imports are named (not default) and check sideEffects: false in package.json

Issue: Dependencies duplicated Solution: Check npm/yarn lock file, use npm dedupe

Issue: Slow build times Solution: Enable caching, use esbuild or swc instead of Babel

Resources