uniswap/ai-toolkit/analyze-bundle

Claude Code and agent skill by uniswap/ai-toolkit

Trust tier 2
  • community
LLM review pending
Source check pending

Checking that the SKILL.md file is still in the repository.

Analyze web application bundle size to find what's making it large and how to shrink it. Always use this skill whenever the user says "analyze the bundle", "what's making my bundle large", "bundle size analysis", "check my webpack output", "why is my app so big", "find heavy dependencies", "optimize the bundle", "check my Vite build size", "bundle is too large", "reduce my JS bundle", "find large modules", "tree-shaking opportunities", "what dependencies are bloating the bundle", "bundle report…

Install

npx vskill@latest install uniswap/ai-toolkit/analyze-bundle

SKILL.md

Bundle Analyzer

Identify what's inflating your web application's bundle, trace it to specific dependencies and import patterns, and produce a prioritized list of optimizations with estimated size savings.

When to Activate

  • User wants to understand what's making their bundle large
  • Initial page load is slow and JavaScript bundle size may be a factor
  • Before or after a dependency update to measure size impact
  • CI is flagging a bundle size regression
  • Preparing to ship a performance improvement and need a baseline
  • Code-splitting, lazy loading, or tree-shaking improvements are being planned

Step 1: Detect Bundler and Stack

Scan for config files to identify the bundler and framework:

Signal fileBundlerAnalysis approach
vite.config.ts / vite.config.jsViteBuild with --report or vite-bundle-visualizer
webpack.config.*Webpackwebpack-bundle-analyzer via stats JSON
next.config.*Next.js (Webpack)@next/bundle-analyzer or source-map-explorer on .next/static/chunks/
rollup.config.*RollupBuild with rollup-plugin-visualizer
esbuild.config.* or esbuild in scriptsesbuild--metafile flag → analyze with esbuild-bundle-analyzer
parcel.config.* / .parcelrcParcelparcel build --detailed-report
turbo.jsonTurbopack/TurborepoCheck individual apps in the monorepo for their bundler

Also check package.json scripts for build commands to understand the build pipeline:

bash
cat package.json | grep -A5 '"scripts"'

If the project uses a monorepo (nx.json, turbo.json, pnpm workspaces), identify which packages have browser bundles before proceeding.

Step 2: Check for Existing Build Artifacts

Before re-building, check whether a recent build already exists:

bash
# Vite / generic
find dist -name "*.js" -mtime -1 2>/dev/null | head -20
ls -lhS dist/ 2>/dev/null | head -20
# Next.js
ls -lhS .next/static/chunks/ 2>/dev/null | head -20
# Create React App / webpack
ls -lhS build/static/js/ 2>/dev/null | head -20

If fresh artifacts are present (modified within the last day), skip rebuilding and use the existing output. Note this in your report.

If no build artifacts exist, run the build in Step 3.

Step 3: Generate Bundle Report

Run the appropriate analysis tool based on the bundler detected in Step 1.

Vite

Check for vite-bundle-visualizer or use the built-in rollup options:

bash
# Using vite-bundle-visualizer (preferred if available)
npx vite-bundle-visualizer --output /tmp/bundle-report.json 2>/dev/null
# Fallback: build with rollup options to emit stats
npm run build -- --mode production 2>/dev/null

After building, read the manifest if present:

bash
cat dist/.vite/manifest.json 2>/dev/null | head -100
Webpack
bash
# Generate stats.json
npx webpack --config webpack.config.js --profile --json > /tmp/webpack-stats.json 2>/dev/null
# If that fails, check if webpack is configured in package.json scripts
npm run build -- --stats 2>/dev/null

Then use webpack-bundle-analyzer in stats mode:

bash
npx webpack-bundle-analyzer /tmp/webpack-stats.json --mode static --report /tmp/bundle-report.html --no-open 2>/dev/null
Next.js
bash
# Check if @next/bundle-analyzer is configured
grep -r "bundle-analyzer\|withBundleAnalyzer" next.config.* 2>/dev/null
# Run with ANALYZE flag if configured
ANALYZE=true npm run build 2>/dev/null
# Fallback: analyze .next/static/chunks directly
ls -lhS .next/static/chunks/*.js 2>/dev/null | head -30
source-map-explorer (Universal Fallback)

When bundler-specific tools aren't available, source-map-explorer works on any build output that includes source maps:

bash
# Ensure source maps exist
ls dist/*.js.map build/static/js/*.js.map .next/static/chunks/*.js.map 2>/dev/null | head -5
# Run source-map-explorer on the detected build output (use only the matching path to
# avoid the second command silently overwriting the first report)
if [ -d dist ]; then
npx source-map-explorer 'dist/*.js' --json > /tmp/sme-report.json 2>/dev/null
elif [ -d build/static/js ]; then
npx source-map-explorer 'build/static/js/*.js' --json > /tmp/sme-report.json 2>/dev/null
fi

Parse the JSON output to extract module sizes.

Raw File Sizes (Minimal Fallback)

If no analysis tool is available and source maps are absent:

bash
# Raw sizes sorted by size
find dist build .next/static/chunks -name "*.js" -not -name "*.map" 2>/dev/null \
| xargs du -h | sort -rh | head -20
# Gzip estimate (multiply raw size by ~0.3 for a rough gzip estimate)
find dist -name "*.js" -not -name "*.map" 2>/dev/null \
| xargs gzip -c | wc -c

Note: raw fallback provides size totals only — no per-module breakdown. Recommend the user install vite-bundle-visualizer or enable source maps for a full analysis.

Step 4: Identify Heaviest Modules and Dependencies

From the report data, extract:

Top Modules by Size

List the 15 largest modules (by parsed/compressed size). For each entry note:

  • Module path or package name
  • Size (raw bytes and gzip estimate if available)
  • Whether it's a production dependency, dev dependency, or application code
  • Whether a lighter alternative exists
Duplicate Packages

Check if the same package appears at multiple versions (common with monorepos and conflicting peer dependencies):

bash
# Preferred: use npm/pnpm/yarn to report all resolved versions — this catches nested
# hoisting conflicts that a flat node_modules scan would miss
npm ls --all --json 2>/dev/null | node -e "
const data = JSON.parse(require('fs').readFileSync('/dev/stdin','utf8'));
const seen = {};
function walk(node, depth) {
if (!node || depth > 10) return;
if (node.name && node.version) {
if (!seen[node.name]) seen[node.name] = new Set();
seen[node.name].add(node.version);
}
for (const dep of Object.values(node.dependencies || {})) walk(dep, depth+1);
}
walk(data, 0);
Object.entries(seen).filter(([,vs])=>vs.size>1)
.forEach(([n,vs])=>console.log(n+': '+[...vs].join(', ')));
" 2>/dev/null | head -20
# Fallback if npm ls is too slow: flat scan (note: excludes nested node_modules,
# so it may miss hoisted duplicates — use npm ls output for authoritative results)
find node_modules -maxdepth 2 -name "package.json" \
| xargs node -e "
const fs=require('fs');
const map={};
process.argv.slice(1).forEach(f=>{
try{
const p=JSON.parse(fs.readFileSync(f,'utf8'));
if(!map[p.name]) map[p.name]=[];
map[p.name].push(p.version);
}catch(e){}
});
Object.entries(map).filter(([,vs])=>vs.length>1)
.forEach(([n,vs])=>console.log(n+': '+vs.join(', ')));
" 2>/dev/null | head -20

Duplicates that appear in multiple versions often land in the bundle multiple times. Flag any duplicate that is both large (>50 KB raw) and frequently used (React, lodash, date-fns, etc.).

Tree-Shaking Issues

Scan for import patterns that defeat tree-shaking. The head -N on each grep below truncates the listing for readability — it is not a finding filter. Re-run each with | wc -l and report the true count, so 40 namespace imports are never written up as 20. (The head -N on the ls -lhS / du | sort -rh commands above is different: those are size-sorted, so truncating genuinely keeps the largest.)

bash
# Namespace imports (import * as X) — barrel imports that pull in everything
grep -r "import \* as" src/ --include="*.ts" --include="*.tsx" --include="*.js" --include="*.jsx" 2>/dev/null | head -20
# Default imports from packages known to have named exports (lodash, date-fns, ramda)
grep -r "import _ from 'lodash'" src/ --include="*.ts" --include="*.tsx" 2>/dev/null | head -5
grep -r "import moment from 'moment'" src/ --include="*.ts" --include="*.tsx" 2>/dev/null | head -5
# Check if problematic packages have tree-shakeable alternatives
grep -r "\"moment\":\|\"lodash\":\|\"rxjs\":" package.json 2>/dev/null

Step 5: Check for Code-Splitting Opportunities

Identify code that could be lazily loaded to reduce the initial bundle:

bash
# Route components loaded eagerly in React Router / Next.js
grep -r "import.*from.*pages\|import.*Router\|createBrowserRouter" src/ --include="*.tsx" --include="*.ts" 2>/dev/null | grep -v "lazy\|dynamic" | head -15
# Heavy components not yet lazy-loaded
grep -r "^import " src/ --include="*.tsx" 2>/dev/null \
| grep -v "from 'react'\|from '@types'\|\.module\." \
| awk '{print $NF}' | sort | uniq -c | sort -rn | head -20
# Check if React.lazy / dynamic() is already used
grep -r "React\.lazy\|import()\|next/dynamic" src/ --include="*.tsx" --include="*.ts" 2>/dev/null | wc -l

Flag routes and large feature components that are imported synchronously but only needed for specific user flows. These are prime candidates for React.lazy() or Next.js dynamic().

Step 6: Report

Output a structured report in three sections.

Bundle Size Summary
Bundler: [detected bundler]
Total raw size: X KB / X MB
Total gzip estimate: X KB / X MB (×0.28 compression ratio)
Largest chunk: [filename] — X KB
Number of chunks: N
Analysis method: [tool used or "raw file sizes"]
Build artifacts: [fresh / regenerated / not found]
Top 10 Heaviest Modules

List each module with size, category (dep / app code), and a one-line note:

1. react-dom — 130 KB (gzip: 42 KB) production dep, required
2. @mui/material — 98 KB (gzip: 31 KB) production dep — consider tree-shaking named imports only
3. lodash — 71 KB (gzip: 25 KB) production dep — NAMESPACE IMPORT detected; switch to named imports or lodash-es
4. moment — 67 KB (gzip: 22 KB) production dep — replace with date-fns (~6 KB gzip) or day.js (~2 KB gzip)
5. [application code]...
Actionable Recommendations

Sort by estimated size saving (largest first). Report every heavy module you found, not only the ones you have a fix for — a 90 KB dependency with no obvious replacement is still the most useful thing in the report, and dropping it at write-up time hides the biggest number on the page. Put those under a Known cost, no fix identified heading with the size and why the usual remedies do not apply, so the reader can make their own call.

## Critical (>20 KB gzip saving each)
### Replace `moment` with `day.js`
Current: 67 KB raw / 22 KB gzip
Target: ~7 KB raw / 2.5 KB gzip
Saving: ~20 KB gzip
Effort: Medium — API is compatible; use codemod or search/replace
Fix: npm uninstall moment && npm install dayjs
Replace: import moment from 'moment' → import dayjs from 'dayjs'
### Fix lodash namespace import
Current: 71 KB raw (full lodash bundle)
Target: ~15 KB raw (only used functions)
Saving: ~15 KB gzip
Effort: Low — change import style
Fix: Replace `import _ from 'lodash'` with named imports: `import { debounce, cloneDeep } from 'lodash-es'`
## High (5–20 KB gzip saving each)
### Lazy-load SettingsPage and AdminDashboard routes
These components are only needed for authenticated admin users but are in the main bundle.
Saving: ~8 KB gzip estimated
Effort: Low
Fix: const SettingsPage = React.lazy(() => import('./pages/SettingsPage'))
## Low (<5 KB gzip saving each)
### [smaller items]

This is the start of the file. Read the full SKILL.md on GitHub.

Security

  • Security scanPassed, 100 of 100Pattern checks on the skill's files.
  • Model reviewNot runA model review is scheduled for the next rescan.

Quality evaluation

  • Task evaluationNot runNo evaluation yet. Run one in Skill Studio.

Source

Popularity

Repository stars
42
Repository forks
12
7-day trend score
19

Stars and forks are for the whole GitHub repository, not this skill alone. Not refreshed yet.

Works with

Any agent vskill installs to: 56 targets in all. These 39 have a page on this site.

  • Claude Code
  • Cursor
  • GitHub Copilot
  • Windsurf
  • Codex
  • Gemini CLI
  • Cline
  • Amp
  • Roo Code
  • Goose
  • Continue
  • Kilo Code
  • Junie
  • Trae
  • OpenHands
  • Qwen Code
  • AI Agent
  • Tabnine Chat
  • Sourcegraph Cody
  • Amazon Q
  • Firebase Genkit
  • Sweep
  • Devin
  • Phind
  • Mentat
  • Claude Desktop
  • Aider
  • GPT Pilot
  • Plandex
  • bolt.new
  • v0
  • Replit Agent
  • Anse
  • TypingMind
  • BetterChatGPT
  • LibreChat
  • Warp AI
  • Pieces
  • Fig AI
Embed badge
vskill VERIFIED badge
[![vskill VERIFIED](https://verified-skill.com/api/v1/skills/uniswap/ai-toolkit/analyze-bundle/badge)](https://verified-skill.com/skills/uniswap/ai-toolkit/analyze-bundle)

Something wrong with this skill or its page? Tell us.