Loading...
Analyzes webpack bundle size when webpack config or entry files are modified
{
"hookConfig": {
"hooks": {
"postToolUse": {
"script": "./.claude/hooks/webpack-bundle-analyzer.sh",
"matchers": [
"write",
"edit"
]
}
}
},
"scriptContent": "#!/bin/bash\n\n# Read the tool input from stdin\nINPUT=$(cat)\nTOOL_NAME=$(echo \"$INPUT\" | jq -r '.tool_name')\nFILE_PATH=$(echo \"$INPUT\" | jq -r '.tool_input.file_path // .tool_input.path // \"\"')\n\nif [ -z \"$FILE_PATH\" ]; then\n exit 0\nfi\n\necho \"📊 Webpack Bundle Analyzer - Analyzing bundle performance...\"\necho \"📄 File: $FILE_PATH\"\n\n# Check if this is a relevant file for bundle analysis\nRELEVANT_FILE=false\n\nif [[ \"$FILE_PATH\" == *webpack.config.js ]] || \\\n [[ \"$FILE_PATH\" == *webpack.config.ts ]] || \\\n [[ \"$FILE_PATH\" == *vite.config.js ]] || \\\n [[ \"$FILE_PATH\" == *vite.config.ts ]] || \\\n [[ \"$FILE_PATH\" == *rollup.config.js ]] || \\\n [[ \"$FILE_PATH\" == *src/index.js ]] || \\\n [[ \"$FILE_PATH\" == *src/index.ts ]] || \\\n [[ \"$FILE_PATH\" == *src/main.js ]] || \\\n [[ \"$FILE_PATH\" == *src/main.ts ]] || \\\n [[ \"$FILE_PATH\" == *package.json ]]; then\n RELEVANT_FILE=true\nfi\n\nif [ \"$RELEVANT_FILE\" = false ]; then\n echo \"ℹ️ File does not require bundle analysis: $FILE_PATH\"\n exit 0\nfi\n\necho \"🔍 Detecting build system and configuration...\"\n\n# Detect build system\nBUILD_SYSTEM=\"unknown\"\nif [ -f \"webpack.config.js\" ] || [ -f \"webpack.config.ts\" ]; then\n BUILD_SYSTEM=\"webpack\"\n echo \"📦 Webpack configuration detected\"\nelif [ -f \"vite.config.js\" ] || [ -f \"vite.config.ts\" ]; then\n BUILD_SYSTEM=\"vite\"\n echo \"⚡ Vite configuration detected\"\nelif [ -f \"rollup.config.js\" ] || [ -f \"rollup.config.ts\" ]; then\n BUILD_SYSTEM=\"rollup\"\n echo \"🎯 Rollup configuration detected\"\nelif [ -f \"package.json\" ] && grep -q '\"react-scripts\"' package.json 2>/dev/null; then\n BUILD_SYSTEM=\"cra\"\n echo \"⚛️ Create React App detected\"\nelif [ -f \"next.config.js\" ] || [ -f \"next.config.ts\" ]; then\n BUILD_SYSTEM=\"next\"\n echo \"🔺 Next.js configuration detected\"\nelse\n echo \"❓ No recognized build system found\"\nfi\n\n# Check for bundle analyzer availability\nANALYZER_AVAILABLE=false\nif command -v npx >/dev/null 2>&1; then\n if npx webpack-bundle-analyzer --version >/dev/null 2>&1; then\n ANALYZER_AVAILABLE=true\n echo \"✅ webpack-bundle-analyzer available\"\n else\n echo \"⚠️ webpack-bundle-analyzer not available - install with: npm install --save-dev webpack-bundle-analyzer\"\n fi\nelse\n echo \"⚠️ npx not available - please install Node.js\"\nfi\n\n# Perform bundle analysis based on build system\ncase \"$BUILD_SYSTEM\" in\n \"webpack\")\n echo \"📊 Analyzing Webpack bundle...\"\n \n # Check if dist directory exists\n if [ ! -d \"dist\" ] && [ ! -d \"build\" ]; then\n echo \"🏗️ Building project to generate bundle...\"\n if npm run build 2>/dev/null; then\n echo \"✅ Build completed successfully\"\n else\n echo \"❌ Build failed - cannot analyze bundle\"\n exit 1\n fi\n fi\n \n # Find stats file or generate one\n STATS_FILE=\"\"\n if [ -f \"dist/stats.json\" ]; then\n STATS_FILE=\"dist/stats.json\"\n elif [ -f \"build/stats.json\" ]; then\n STATS_FILE=\"build/stats.json\"\n else\n echo \"📈 Generating webpack stats...\"\n if npx webpack --profile --json > webpack-stats.json 2>/dev/null; then\n STATS_FILE=\"webpack-stats.json\"\n echo \"✅ Stats file generated: $STATS_FILE\"\n else\n echo \"❌ Failed to generate webpack stats\"\n exit 1\n fi\n fi\n \n # Run bundle analyzer\n if [ \"$ANALYZER_AVAILABLE\" = true ] && [ -n \"$STATS_FILE\" ]; then\n echo \"🔍 Running bundle analysis...\"\n if npx webpack-bundle-analyzer \"$STATS_FILE\" --mode static --report bundle-report.html --no-open 2>/dev/null; then\n echo \"✅ Bundle analysis completed\"\n echo \"📊 Report saved to: bundle-report.html\"\n echo \"🌐 View report: file://$(pwd)/bundle-report.html\"\n else\n echo \"⚠️ Bundle analysis failed\"\n fi\n fi\n ;;\n \"vite\")\n echo \"⚡ Analyzing Vite bundle...\"\n \n # Check if Vite has bundle analysis plugin\n if grep -q 'vite-bundle-analyzer\\|rollup-plugin-analyzer' package.json 2>/dev/null; then\n echo \"📊 Running Vite bundle analysis...\"\n if npm run build -- --analyze 2>/dev/null; then\n echo \"✅ Vite bundle analysis completed\"\n else\n echo \"⚠️ Vite bundle analysis failed\"\n fi\n else\n echo \"💡 Install vite-bundle-analyzer for detailed analysis:\"\n echo \" npm install --save-dev vite-bundle-analyzer\"\n \n # Basic build size analysis\n echo \"📏 Running basic build analysis...\"\n if npm run build 2>/dev/null; then\n if [ -d \"dist\" ]; then\n echo \"📊 Build output analysis:\"\n find dist -name \"*.js\" -exec du -h {} \\; | sort -hr | head -10\n fi\n fi\n fi\n ;;\n \"next\")\n echo \"🔺 Analyzing Next.js bundle...\"\n \n if grep -q '@next/bundle-analyzer' package.json 2>/dev/null; then\n echo \"📊 Running Next.js bundle analysis...\"\n if ANALYZE=true npm run build 2>/dev/null; then\n echo \"✅ Next.js bundle analysis completed\"\n else\n echo \"⚠️ Next.js bundle analysis failed\"\n fi\n else\n echo \"💡 Install @next/bundle-analyzer for detailed analysis:\"\n echo \" npm install --save-dev @next/bundle-analyzer\"\n fi\n ;;\n \"cra\")\n echo \"⚛️ Analyzing Create React App bundle...\"\n \n if npm list --depth=0 | grep -q 'source-map-explorer' 2>/dev/null; then\n echo \"📊 Running source-map-explorer...\"\n if npm run build && npx source-map-explorer 'build/static/js/*.js' 2>/dev/null; then\n echo \"✅ CRA bundle analysis completed\"\n else\n echo \"⚠️ CRA bundle analysis failed\"\n fi\n else\n echo \"💡 Install source-map-explorer for detailed analysis:\"\n echo \" npm install --save-dev source-map-explorer\"\n fi\n ;;\n *)\n echo \"❓ Unknown build system - attempting generic analysis\"\n \n # Try to analyze any existing build output\n for dir in dist build public; do\n if [ -d \"$dir\" ]; then\n echo \"📊 Analyzing $dir directory:\"\n find \"$dir\" -name \"*.js\" -o -name \"*.css\" | head -10 | while read -r file; do\n size=$(du -h \"$file\" 2>/dev/null | cut -f1)\n echo \" • $file: $size\"\n done\n fi\n done\n ;;\nesac\n\n# General optimization suggestions\necho \"\"\necho \"💡 Bundle Optimization Tips:\"\necho \" • Enable tree-shaking to remove unused code\"\necho \" • Use dynamic imports for code splitting\"\necho \" • Optimize images and static assets\"\necho \" • Use compression (gzip/brotli) for production\"\necho \" • Analyze and remove large unnecessary dependencies\"\necho \" • Use webpack-bundle-analyzer for detailed insights\"\necho \" • Consider lazy loading for non-critical components\"\necho \" • Review and optimize polyfills\"\n\necho \"\"\necho \"📊 Bundle Analysis Tools:\"\necho \" • Webpack: webpack-bundle-analyzer\"\necho \" • Vite: vite-bundle-analyzer\"\necho \" • Next.js: @next/bundle-analyzer\"\necho \" • CRA: source-map-explorer\"\necho \" • General: bundlephobia.com for dependency analysis\"\n\necho \"\"\necho \"🎯 Bundle analysis complete!\"\n\nexit 0"
}.claude/hooks/~/.claude/hooks/{
"hooks": {
"postToolUse": {
"script": "./.claude/hooks/webpack-bundle-analyzer.sh",
"matchers": [
"write",
"edit"
]
}
}
}#!/bin/bash
# Read the tool input from stdin
INPUT=$(cat)
TOOL_NAME=$(echo "$INPUT" | jq -r '.tool_name')
FILE_PATH=$(echo "$INPUT" | jq -r '.tool_input.file_path // .tool_input.path // ""')
if [ -z "$FILE_PATH" ]; then
exit 0
fi
echo "📊 Webpack Bundle Analyzer - Analyzing bundle performance..."
echo "📄 File: $FILE_PATH"
# Check if this is a relevant file for bundle analysis
RELEVANT_FILE=false
if [[ "$FILE_PATH" == *webpack.config.js ]] || \
[[ "$FILE_PATH" == *webpack.config.ts ]] || \
[[ "$FILE_PATH" == *vite.config.js ]] || \
[[ "$FILE_PATH" == *vite.config.ts ]] || \
[[ "$FILE_PATH" == *rollup.config.js ]] || \
[[ "$FILE_PATH" == *src/index.js ]] || \
[[ "$FILE_PATH" == *src/index.ts ]] || \
[[ "$FILE_PATH" == *src/main.js ]] || \
[[ "$FILE_PATH" == *src/main.ts ]] || \
[[ "$FILE_PATH" == *package.json ]]; then
RELEVANT_FILE=true
fi
if [ "$RELEVANT_FILE" = false ]; then
echo "ℹ️ File does not require bundle analysis: $FILE_PATH"
exit 0
fi
echo "🔍 Detecting build system and configuration..."
# Detect build system
BUILD_SYSTEM="unknown"
if [ -f "webpack.config.js" ] || [ -f "webpack.config.ts" ]; then
BUILD_SYSTEM="webpack"
echo "📦 Webpack configuration detected"
elif [ -f "vite.config.js" ] || [ -f "vite.config.ts" ]; then
BUILD_SYSTEM="vite"
echo "⚡ Vite configuration detected"
elif [ -f "rollup.config.js" ] || [ -f "rollup.config.ts" ]; then
BUILD_SYSTEM="rollup"
echo "🎯 Rollup configuration detected"
elif [ -f "package.json" ] && grep -q '"react-scripts"' package.json 2>/dev/null; then
BUILD_SYSTEM="cra"
echo "⚛️ Create React App detected"
elif [ -f "next.config.js" ] || [ -f "next.config.ts" ]; then
BUILD_SYSTEM="next"
echo "🔺 Next.js configuration detected"
else
echo "❓ No recognized build system found"
fi
# Check for bundle analyzer availability
ANALYZER_AVAILABLE=false
if command -v npx >/dev/null 2>&1; then
if npx webpack-bundle-analyzer --version >/dev/null 2>&1; then
ANALYZER_AVAILABLE=true
echo "✅ webpack-bundle-analyzer available"
else
echo "⚠️ webpack-bundle-analyzer not available - install with: npm install --save-dev webpack-bundle-analyzer"
fi
else
echo "⚠️ npx not available - please install Node.js"
fi
# Perform bundle analysis based on build system
case "$BUILD_SYSTEM" in
"webpack")
echo "📊 Analyzing Webpack bundle..."
# Check if dist directory exists
if [ ! -d "dist" ] && [ ! -d "build" ]; then
echo "🏗️ Building project to generate bundle..."
if npm run build 2>/dev/null; then
echo "✅ Build completed successfully"
else
echo "❌ Build failed - cannot analyze bundle"
exit 1
fi
fi
# Find stats file or generate one
STATS_FILE=""
if [ -f "dist/stats.json" ]; then
STATS_FILE="dist/stats.json"
elif [ -f "build/stats.json" ]; then
STATS_FILE="build/stats.json"
else
echo "📈 Generating webpack stats..."
if npx webpack --profile --json > webpack-stats.json 2>/dev/null; then
STATS_FILE="webpack-stats.json"
echo "✅ Stats file generated: $STATS_FILE"
else
echo "❌ Failed to generate webpack stats"
exit 1
fi
fi
# Run bundle analyzer
if [ "$ANALYZER_AVAILABLE" = true ] && [ -n "$STATS_FILE" ]; then
echo "🔍 Running bundle analysis..."
if npx webpack-bundle-analyzer "$STATS_FILE" --mode static --report bundle-report.html --no-open 2>/dev/null; then
echo "✅ Bundle analysis completed"
echo "📊 Report saved to: bundle-report.html"
echo "🌐 View report: file://$(pwd)/bundle-report.html"
else
echo "⚠️ Bundle analysis failed"
fi
fi
;;
"vite")
echo "⚡ Analyzing Vite bundle..."
# Check if Vite has bundle analysis plugin
if grep -q 'vite-bundle-analyzer\|rollup-plugin-analyzer' package.json 2>/dev/null; then
echo "📊 Running Vite bundle analysis..."
if npm run build -- --analyze 2>/dev/null; then
echo "✅ Vite bundle analysis completed"
else
echo "⚠️ Vite bundle analysis failed"
fi
else
echo "💡 Install vite-bundle-analyzer for detailed analysis:"
echo " npm install --save-dev vite-bundle-analyzer"
# Basic build size analysis
echo "📏 Running basic build analysis..."
if npm run build 2>/dev/null; then
if [ -d "dist" ]; then
echo "📊 Build output analysis:"
find dist -name "*.js" -exec du -h {} \; | sort -hr | head -10
fi
fi
fi
;;
"next")
echo "🔺 Analyzing Next.js bundle..."
if grep -q '@next/bundle-analyzer' package.json 2>/dev/null; then
echo "📊 Running Next.js bundle analysis..."
if ANALYZE=true npm run build 2>/dev/null; then
echo "✅ Next.js bundle analysis completed"
else
echo "⚠️ Next.js bundle analysis failed"
fi
else
echo "💡 Install @next/bundle-analyzer for detailed analysis:"
echo " npm install --save-dev @next/bundle-analyzer"
fi
;;
"cra")
echo "⚛️ Analyzing Create React App bundle..."
if npm list --depth=0 | grep -q 'source-map-explorer' 2>/dev/null; then
echo "📊 Running source-map-explorer..."
if npm run build && npx source-map-explorer 'build/static/js/*.js' 2>/dev/null; then
echo "✅ CRA bundle analysis completed"
else
echo "⚠️ CRA bundle analysis failed"
fi
else
echo "💡 Install source-map-explorer for detailed analysis:"
echo " npm install --save-dev source-map-explorer"
fi
;;
*)
echo "❓ Unknown build system - attempting generic analysis"
# Try to analyze any existing build output
for dir in dist build public; do
if [ -d "$dir" ]; then
echo "📊 Analyzing $dir directory:"
find "$dir" -name "*.js" -o -name "*.css" | head -10 | while read -r file; do
size=$(du -h "$file" 2>/dev/null | cut -f1)
echo " • $file: $size"
done
fi
done
;;
esac
# General optimization suggestions
echo ""
echo "💡 Bundle Optimization Tips:"
echo " • Enable tree-shaking to remove unused code"
echo " • Use dynamic imports for code splitting"
echo " • Optimize images and static assets"
echo " • Use compression (gzip/brotli) for production"
echo " • Analyze and remove large unnecessary dependencies"
echo " • Use webpack-bundle-analyzer for detailed insights"
echo " • Consider lazy loading for non-critical components"
echo " • Review and optimize polyfills"
echo ""
echo "📊 Bundle Analysis Tools:"
echo " • Webpack: webpack-bundle-analyzer"
echo " • Vite: vite-bundle-analyzer"
echo " • Next.js: @next/bundle-analyzer"
echo " • CRA: source-map-explorer"
echo " • General: bundlephobia.com for dependency analysis"
echo ""
echo "🎯 Bundle analysis complete!"
exit 0Build triggered on every config edit is slow
Add build skip flag or cache check: `if [ -f .bundle-analyzed-$(md5sum webpack.config.js | cut -d' ' -f1) ]; then exit 0; fi` to track analyzed configs and skip rebuilds for unchanged hashes.
webpack-bundle-analyzer opens browser automatically
Hook uses `--no-open` flag: `npx webpack-bundle-analyzer "$STATS_FILE" --mode static --report bundle-report.html --no-open`. Verify flag is present in script line 154 to prevent browser launch.
Stats file generation fails with webpack errors
Check webpack config validity first: `npx webpack --config webpack.config.js --json > /dev/null 2>&1` to test. If fails, examine error with `npx webpack --profile --json 2>&1 | tee webpack-errors.log`
Vite build doesn't support --analyze flag
Install plugin: `npm i -D rollup-plugin-visualizer`, add to vite.config: `import { visualizer } from 'rollup-plugin-visualizer'; plugins: [visualizer()]`, rebuild.
Hook detects wrong build system for monorepo
Detection scans root only. For workspace builds, modify check: `if [[ "$FILE_PATH" == packages/app/* ]]; then cd packages/app; BUILD_SYSTEM=...; fi`
Loading reviews...
Join our community of Claude power users. No spam, unsubscribe anytime.
Automated accessibility testing and compliance checking for web applications following WCAG guidelines
Automatically generates or updates API documentation when endpoint files are modified
Automatically formats code files after Claude writes or edits them using Prettier, Black, or other formatters