Agent skill
bundle-optimizer
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.
Install this agent skill to your Project
npx add-skill https://github.com/majiayu000/claude-skill-registry/tree/main/skills/development/bundle-optimizer-joshtol-emotive-engine
SKILL.md
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
Didn't find tool you were looking for?