bundle-analysis

Bundle Analysis Skill

Safety Notice

This listing is imported from skills.sh public index metadata. Review upstream SKILL.md and repository scripts before running.

Copy this and send it to your AI assistant to learn

Install skill "bundle-analysis" with this command: npx skills add sgcarstrends/sgcarstrends/sgcarstrends-sgcarstrends-bundle-analysis

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

Install bundle analyzer

pnpm add -D @next/bundle-analyzer

Or as dev dependency in web app

cd apps/web pnpm add -D @next/bundle-analyzer

Configuration

// apps/web/next.config.ts import 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

Analyze production bundle

cd apps/web ANALYZE=true pnpm build

Opens two HTML reports in browser:

- client.html: Client-side bundle

- server.html: Server-side bundle

Analyze specific environment

ANALYZE=true NODE_ENV=production pnpm build

Save report to file

ANALYZE=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

Find large packages

cd apps/web pnpm list --depth=0 | sort -k2 -n

Example output:

lodash 1.2 MB

moment 500 KB

recharts 300 KB

@heroui/react 250 KB

Solutions:

// ❌ Import entire library import _ from "lodash"; import moment from "moment";

// ✅ Import only what you need import debounce from "lodash/debounce"; import groupBy from "lodash/groupBy";

// ✅ Use lighter alternatives import { format } from "date-fns"; // Instead of moment import dayjs from "dayjs"; // Smaller than moment

  1. Duplicate Dependencies

Check for duplicates

pnpm list <package-name>

Example: Multiple versions of react

pnpm list react

Output:

@sgcarstrends/web

├── react@18.3.0

└─┬ some-package

└── react@18.2.0 # Duplicate!

Solutions:

// package.json { "pnpm": { "overrides": { "react": "18.3.0", "react-dom": "18.3.0" } } }

  1. Missing Code Splitting

// ❌ Import heavy component directly import Chart from "@/components/Chart";

export default function Page() { return <Chart data={data} />; }

// ✅ Dynamic import with code splitting import 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} />; }

  1. Large JSON/Data Files

// ❌ Import large JSON files import brands from "@/data/car-brands.json"; // 500KB

// ✅ Load dynamically export async function getBrands() { const response = await fetch("/api/brands"); return response.json(); }

// ✅ Or use dynamic import export async function getBrands() { const { default: brands } = await import("@/data/car-brands.json"); return brands; }

Optimization Techniques

  1. Tree Shaking

// ✅ Named imports enable tree shaking import { Button, Card } from "@heroui/react";

// ❌ Default import includes everything import HeroUI from "@heroui/react";

Verify tree shaking:

// package.json { "sideEffects": false // Enable aggressive tree shaking }

// Or specify side-effect files { "sideEffects": [".css", ".scss"] }

  1. Code Splitting by Route

// 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 splitting const HeavyComponent = dynamic(() => import("./HeavyComponent"));

  1. Lazy Loading

// ✅ 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> ); }

  1. Optimize Dependencies

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

  1. Image Optimization

// ✅ Use Next.js Image component import Image from "next/image";

export default function Logo() { return ( <Image src="/logo.png" alt="Logo" width={200} height={100} priority // For above-fold images quality={75} // Reduce quality if acceptable /> ); }

// ✅ Use modern formats // - WebP: 25-35% smaller than JPEG/PNG // - AVIF: 50% smaller than JPEG (if supported)

  1. Font Optimization

// app/layout.tsx import { Inter } from "next/font/google";

// ✅ Load only needed weights and subsets const inter = Inter({ subsets: ["latin"], weight: ["400", "600", "700"], // Only load what you use display: "swap", preload: true, });

export default function RootLayout({ children }) { return ( <html lang="en" className={inter.className}> <body>{children}</body> </html> ); }

Advanced Analysis

Webpack Bundle Analyzer

For custom webpack configs

pnpm add -D webpack-bundle-analyzer

View detailed dependency tree

ANALYZE=true pnpm build

Source Map Explorer

Analyze source maps

pnpm add -D source-map-explorer

Generate production build with source maps

pnpm build

Analyze

npx source-map-explorer '.next/static/chunks/*.js'

Bundle Buddy

Visualize bundle relationships

npx bundle-buddy '.next/**/*.js.map'

Monitoring Bundle Size

CI Bundle Size Check

.github/workflows/bundle-size.yml

name: Bundle Size Check

on: pull_request: branches: [main]

jobs: bundle-size: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: pnpm/action-setup@v2 - uses: actions/setup-node@v4 with: node-version: 20 cache: "pnpm"

  - name: Install dependencies
    run: pnpm install

  - name: Build
    run: pnpm -F @sgcarstrends/web build

  - name: Analyze bundle
    run: |
      BUNDLE_SIZE=$(du -sh apps/web/.next/static | cut -f1)
      echo "Bundle size: $BUNDLE_SIZE"

      # Fail if bundle exceeds limit
      SIZE_KB=$(du -sk apps/web/.next/static | cut -f1)
      if [ $SIZE_KB -gt 500 ]; then
        echo "Bundle size exceeds 500KB!"
        exit 1
      fi

  - name: Comment PR
    uses: actions/github-script@v6
    with:
      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

Track bundle size over time

echo "$(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

// apps/web/next.config.ts const nextConfig: NextConfig = { // Warn if bundles exceed limits onDemandEntries: { maxInactiveAge: 25 * 1000, pagesBufferLength: 2, },

// Set performance budgets experimental: { optimizeCss: true, optimizePackageImports: ["@heroui/react", "recharts"], }, };

Lighthouse CI

.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

✅ Always measure first

ANALYZE=true pnpm build

Identify actual bottlenecks

Don't prematurely optimize

  1. Prioritize Critical Path

// ✅ Load critical resources first // Above-fold content, essential JS/CSS

// ❌ Don't block initial render // Defer analytics, chat widgets, etc.

  1. Use External CDN

// For heavy third-party libraries // Load from CDN instead of bundling

// next.config.ts const nextConfig: NextConfig = { experimental: { externalDir: true, }, };

  1. Regular Audits

✅ Run bundle analysis regularly

- Before each release

- When adding dependencies

- After major refactors

ANALYZE=true pnpm build

Troubleshooting

Bundle Size Not Reducing

Issue: Optimizations not working

Solution: Check production build

Ensure building for production

NODE_ENV=production pnpm build

Verify minification

cat .next/static/chunks/main-*.js | head -n 1

Should be minified (single line)

Analyzer Not Opening

Issue: Bundle analyzer not showing reports

Solution: Check environment variable

Ensure ANALYZE is set

echo $ANALYZE # Should print "true"

Run explicitly

cd apps/web ANALYZE=true pnpm build

Check for errors in build output

Large Unexplained Bundle

Issue: Bundle larger than expected

Solution: Investigate with source-map-explorer

pnpm build npx source-map-explorer '.next/static/chunks/*.js' --html bundle-report.html

Open bundle-report.html to see breakdown

References

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

Source Transparency

This detail page is rendered from real SKILL.md content. Trust labels are metadata-based hints, not a safety guarantee.

Related Skills

Related by shared tags or category signals.

Research

coverage-analysis

No summary provided by upstream source.

Repository SourceNeeds Review
General

framer-motion-animations

No summary provided by upstream source.

Repository SourceNeeds Review
General

shadcn-components

No summary provided by upstream source.

Repository SourceNeeds Review
General

api-testing

No summary provided by upstream source.

Repository SourceNeeds Review