<< All versions
Skill v1.0.1
currentAutomated scan100/100majiayu000/claude-skill-registry/bundle-analysis-majiayu000-claude-skill-regist
3 files
──Details
PublishedMay 15, 2026 at 11:30 PM
Content Hashsha256:15b47daf34f1b01a...
Git SHA4a67e6f2e6a1
Bump Typepatch
──Files
Files (1 file, 12.7 KB)
SKILL.md12.7 KBactive
SKILL.md · 601 lines · 12.7 KB
version: "1.0.1" name: bundle-analysis description: Analyze and optimize JavaScript bundle size, identify large dependencies, and improve load times. Use when bundles are large, investigating performance issues, or optimizing frontend assets. allowed-tools: Read, Edit, Write, Bash, Grep
Bundle Analysis Skill
This skill helps you analyze and optimize JavaScript bundle sizes for Next.js and web applications.
When to Use This Skill
- Large bundle sizes (>500KB)
- Slow initial page loads
- High First Contentful Paint (FCP)
- Investigating bundle composition
- Identifying duplicate dependencies
- Optimizing production builds
- Reducing Time to Interactive (TTI)
Bundle Size Goals
- Initial bundle: <200KB (gzipped)
- First Load JS: <300KB total
- Route chunks: <100KB each
- Vendor chunks: <150KB
- Time to Interactive: <3s on 3G
Next.js Bundle Analyzer
Setup
bash
# Install bundle analyzerpnpm add -D @next/bundle-analyzer# Or as dev dependency in web appcd apps/webpnpm add -D @next/bundle-analyzer
Configuration
typescript
// apps/web/next.config.tsimport type { NextConfig } from "next";import withBundleAnalyzer from "@next/bundle-analyzer";const bundleAnalyzer = withBundleAnalyzer({enabled: process.env.ANALYZE === "true",});const nextConfig: NextConfig = {// ... your config};export default bundleAnalyzer(nextConfig);
Running Analysis
bash
# Analyze production bundlecd apps/webANALYZE=true pnpm build# Opens two HTML reports in browser:# - client.html: Client-side bundle# - server.html: Server-side bundle# Analyze specific environmentANALYZE=true NODE_ENV=production pnpm build# Save report to fileANALYZE=true pnpm build > bundle-report.txt
Reading Bundle Reports
Bundle Analyzer Output
Page Size First Load JS┌ ○ / 5.2 kB 120 kB├ /_app 0 B 115 kB├ ○ /404 3.1 kB 118 kB├ λ /api/cars 0 B 115 kB├ ○ /blog 8.5 kB 128 kB├ ○ /blog/[slug] 12.3 kB 132 kB└ ○ /charts 45.2 kB 165 kB+ First Load JS shared by all 115 kB├ chunks/framework-[hash].js 42 kB├ chunks/main-[hash].js 28 kB├ chunks/pages/_app-[hash].js 35 kB└ chunks/webpack-[hash].js 10 kB○ (Static) automatically rendered as static HTMLλ (Server) server-side renders at runtime
Key Metrics:
- Size: Page-specific JavaScript
- First Load JS: Total JS loaded for initial render
- Shared chunks: Code shared across pages
Interactive Report
Open client.html or server.html in browser:
- Large boxes: Heavy dependencies
- Colors: Different packages
- Hover: See exact sizes
- Click: Drill down into dependencies
Common Issues
1. Large Dependencies
bash
# Find large packagescd apps/webpnpm list --depth=0 | sort -k2 -n# Example output:# lodash 1.2 MB# moment 500 KB# recharts 300 KB# @heroui/react 250 KB
Solutions:
typescript
// ❌ Import entire libraryimport _ from "lodash";import moment from "moment";// ✅ Import only what you needimport debounce from "lodash/debounce";import groupBy from "lodash/groupBy";// ✅ Use lighter alternativesimport { format } from "date-fns"; // Instead of momentimport dayjs from "dayjs"; // Smaller than moment
2. Duplicate Dependencies
bash
# Check for duplicatespnpm list <package-name># Example: Multiple versions of reactpnpm list react# Output:# @sgcarstrends/web# ├── react@18.3.0# └─┬ some-package# └── react@18.2.0 # Duplicate!
Solutions:
json
// package.json{"pnpm": {"overrides": {"react": "18.3.0","react-dom": "18.3.0"}}}
3. Missing Code Splitting
typescript
// ❌ Import heavy component directlyimport Chart from "@/components/Chart";export default function Page() {return <Chart data={data} />;}// ✅ Dynamic import with code splittingimport dynamic from "next/dynamic";const Chart = dynamic(() => import("@/components/Chart"), {loading: () => <div>Loading chart...</div>,ssr: false, // Client-side only if needed});export default function Page() {return <Chart data={data} />;}
4. Large JSON/Data Files
typescript
// ❌ Import large JSON filesimport brands from "@/data/car-brands.json"; // 500KB// ✅ Load dynamicallyexport async function getBrands() {const response = await fetch("/api/brands");return response.json();}// ✅ Or use dynamic importexport async function getBrands() {const { default: brands } = await import("@/data/car-brands.json");return brands;}
Optimization Techniques
1. Tree Shaking
typescript
// ✅ Named imports enable tree shakingimport { Button, Card } from "@heroui/react";// ❌ Default import includes everythingimport HeroUI from "@heroui/react";
Verify tree shaking:
json
// package.json{"sideEffects": false // Enable aggressive tree shaking}// Or specify side-effect files{"sideEffects": ["*.css", "*.scss"]}
2. Code Splitting by Route
typescript
// Next.js automatically code-splits by route// Each page becomes a separate chunk// app/page.tsx -> chunk for /// app/blog/page.tsx -> chunk for /blog// app/charts/page.tsx -> chunk for /charts// ✅ Additional manual splittingconst HeavyComponent = dynamic(() => import("./HeavyComponent"));
3. Lazy Loading
typescript
// ✅ Load components on interaction"use client";import { useState } from "react";import dynamic from "next/dynamic";const CommentForm = dynamic(() => import("./CommentForm"));export default function BlogPost() {const [showComments, setShowComments] = useState(false);return (<div><article>{/* post content */}</article><button onClick={() => setShowComments(true)}>Show Comments</button>{showComments && <CommentForm />}</div>);}
4. Optimize Dependencies
bash
# Replace heavy packages with lighter alternatives# ❌ moment (500KB)pnpm remove moment# ✅ date-fns (30KB) or dayjs (7KB)pnpm add date-fns# ❌ lodash (full library)# ✅ lodash-es (ESM with tree-shaking)pnpm add lodash-es# ❌ axios (for simple requests)# ✅ native fetch or ky (12KB)pnpm add ky
5. Image Optimization
typescript
// ✅ Use Next.js Image componentimport Image from "next/image";export default function Logo() {return (<Imagesrc="/logo.png"alt="Logo"width={200}height={100}priority // For above-fold imagesquality={75} // Reduce quality if acceptable/>);}// ✅ Use modern formats// - WebP: 25-35% smaller than JPEG/PNG// - AVIF: 50% smaller than JPEG (if supported)
6. Font Optimization
typescript
// app/layout.tsximport { Inter } from "next/font/google";// ✅ Load only needed weights and subsetsconst inter = Inter({subsets: ["latin"],weight: ["400", "600", "700"], // Only load what you usedisplay: "swap",preload: true,});export default function RootLayout({ children }) {return (<html lang="en" className={inter.className}><body>{children}</body></html>);}
Advanced Analysis
Webpack Bundle Analyzer
bash
# For custom webpack configspnpm add -D webpack-bundle-analyzer# View detailed dependency treeANALYZE=true pnpm build
Source Map Explorer
bash
# Analyze source mapspnpm add -D source-map-explorer# Generate production build with source mapspnpm build# Analyzenpx source-map-explorer '.next/static/chunks/*.js'
Bundle Buddy
bash
# Visualize bundle relationshipsnpx bundle-buddy '.next/**/*.js.map'
Monitoring Bundle Size
CI Bundle Size Check
yaml
# .github/workflows/bundle-size.ymlname: Bundle Size Checkon:pull_request:branches: [main]jobs:bundle-size:runs-on: ubuntu-lateststeps:- uses: actions/checkout@v4- uses: pnpm/action-setup@v2- uses: actions/setup-node@v4with:node-version: 20cache: "pnpm"- name: Install dependenciesrun: pnpm install- name: Buildrun: pnpm -F @sgcarstrends/web build- name: Analyze bundlerun: |BUNDLE_SIZE=$(du -sh apps/web/.next/static | cut -f1)echo "Bundle size: $BUNDLE_SIZE"# Fail if bundle exceeds limitSIZE_KB=$(du -sk apps/web/.next/static | cut -f1)if [ $SIZE_KB -gt 500 ]; thenecho "Bundle size exceeds 500KB!"exit 1fi- name: Comment PRuses: actions/github-script@v6with:script: |github.rest.issues.createComment({issue_number: context.issue.number,owner: context.repo.owner,repo: context.repo.repo,body: '📦 Bundle size: ${{ env.BUNDLE_SIZE }}'})
Bundle Size Tracking
bash
# Track bundle size over timeecho "$(date +%Y-%m-%d),$(du -sk apps/web/.next/static | cut -f1)" >> bundle-history.csv# Plot with gnuplot or spreadsheet
Performance Budgets
next.config.ts
typescript
// apps/web/next.config.tsconst nextConfig: NextConfig = {// Warn if bundles exceed limitsonDemandEntries: {maxInactiveAge: 25 * 1000,pagesBufferLength: 2,},// Set performance budgetsexperimental: {optimizeCss: true,optimizePackageImports: ["@heroui/react", "recharts"],},};
Lighthouse CI
yaml
# .lighthouserc.json{"ci": {"collect": {"startServerCommand": "pnpm start","url": ["http://localhost:3000", "http://localhost:3000/charts"]},"assert": {"assertions": {"categories:performance": ["error", { "minScore": 0.9 }],"resource-summary:script:size": ["error", { "maxNumericValue": 300000 }],"total-byte-weight": ["error", { "maxNumericValue": 500000 }]}}}}
Best Practices
1. Measure Before Optimizing
bash
# ✅ Always measure firstANALYZE=true pnpm build# Identify actual bottlenecks# Don't prematurely optimize
2. Prioritize Critical Path
typescript
// ✅ Load critical resources first// Above-fold content, essential JS/CSS// ❌ Don't block initial render// Defer analytics, chat widgets, etc.
3. Use External CDN
typescript
// For heavy third-party libraries// Load from CDN instead of bundling// next.config.tsconst nextConfig: NextConfig = {experimental: {externalDir: true,},};
4. Regular Audits
bash
# ✅ Run bundle analysis regularly# - Before each release# - When adding dependencies# - After major refactorsANALYZE=true pnpm build
Troubleshooting
Bundle Size Not Reducing
bash
# Issue: Optimizations not working# Solution: Check production build# Ensure building for productionNODE_ENV=production pnpm build# Verify minificationcat .next/static/chunks/main-*.js | head -n 1# Should be minified (single line)
Analyzer Not Opening
bash
# Issue: Bundle analyzer not showing reports# Solution: Check environment variable# Ensure ANALYZE is setecho $ANALYZE # Should print "true"# Run explicitlycd apps/webANALYZE=true pnpm build# Check for errors in build output
Large Unexplained Bundle
bash
# Issue: Bundle larger than expected# Solution: Investigate with source-map-explorerpnpm buildnpx source-map-explorer '.next/static/chunks/*.js' --html bundle-report.html# Open bundle-report.html to see breakdown
References
- Next.js Bundle Analyzer: https://www.npmjs.com/package/@next/bundle-analyzer
- Webpack Bundle Analyzer: https://github.com/webpack-contrib/webpack-bundle-analyzer
- Web.dev Bundle Size: https://web.dev/your-first-performance-budget/
- Next.js Optimization: https://nextjs.org/docs/app/building-your-application/optimizing
- Related files:
apps/web/next.config.ts- Next.js configuration- Root CLAUDE.md - Performance guidelines
Best Practices Summary
- Analyze Regularly: Check bundle size before releases
- Code Split: Use dynamic imports for heavy components
- Tree Shake: Use named imports, mark side effects
- Optimize Dependencies: Replace heavy packages with lighter alternatives
- Lazy Load: Defer non-critical resources
- Monitor: Set up CI checks and performance budgets
- Use CDN: Offload heavy third-party libraries
- Image Optimization: Use Next.js Image with WebP/AVIF