Agent Skills: Bundle Performance

Monitor JavaScript bundle size and execution performance. Use when tracking bundle size, identifying large chunks, or optimizing load performance.

UncategorizedID: nexus-labs-automation/web-observability/bundle-performance

Install this agent skill to your local

pnpm dlx add-skill https://github.com/nexus-labs-automation/web-observability/tree/HEAD/skills/bundle-performance

Skill Files

Browse the full folder contents for bundle-performance.

Download Skill

Loading file tree…

skills/bundle-performance/SKILL.md

Skill Metadata

Name
bundle-performance
Description
Monitor JavaScript bundle size and execution performance. Use when tracking bundle size, identifying large chunks, or optimizing load performance.

Bundle Performance

Monitor JavaScript bundle size and its impact on performance.

Why Bundle Size Matters

| Bundle Size | LCP Impact | INP Impact | |-------------|------------|------------| | <100KB | Minimal | Minimal | | 100-300KB | Moderate | Noticeable | | 300-500KB | Significant | Degraded | | >500KB | Severe | Poor |

Performance Budgets

| Metric | Good | Warning | Critical | |--------|------|---------|----------| | Initial JS | <200KB | <500KB | >500KB | | Per-route chunk | <100KB | <200KB | >200KB | | Total JS | <500KB | <1MB | >1MB | | First Load | <3s on 3G | <5s | >5s |

Build-Time Analysis

Vite

// vite.config.ts
import { visualizer } from 'rollup-plugin-visualizer';

export default defineConfig({
  build: {
    rollupOptions: {
      output: {
        manualChunks: {
          vendor: ['react', 'react-dom'],
          utils: ['lodash', 'date-fns'],
        },
      },
    },
  },
  plugins: [
    visualizer({
      filename: 'dist/stats.html',
      gzipSize: true,
      brotliSize: true,
    }),
  ],
});

Webpack (Next.js)

// next.config.js
const withBundleAnalyzer = require('@next/bundle-analyzer')({
  enabled: process.env.ANALYZE === 'true',
});

module.exports = withBundleAnalyzer({
  // your config
});

// Run: ANALYZE=true npm run build

Runtime Monitoring

Resource Timing API

function trackBundleLoading() {
  const observer = new PerformanceObserver((list) => {
    for (const entry of list.getEntries()) {
      if (entry.name.endsWith('.js')) {
        trackResourceLoad({
          name: new URL(entry.name).pathname,
          size_bytes: (entry as PerformanceResourceTiming).transferSize,
          duration_ms: entry.duration,
          type: 'javascript',
        });
      }
    }
  });

  observer.observe({ type: 'resource', buffered: true });
}

Long Tasks API

function trackLongTasks() {
  const observer = new PerformanceObserver((list) => {
    for (const entry of list.getEntries()) {
      trackLongTask({
        duration_ms: entry.duration,
        start_time_ms: entry.startTime,
        // Attribution for debugging
        name: (entry as any).attribution?.[0]?.name || 'unknown',
        container_type: (entry as any).attribution?.[0]?.containerType,
      });

      // Alert on very long tasks
      if (entry.duration > 100) {
        captureMessage('Long task detected', {
          level: 'warning',
          extra: {
            duration_ms: entry.duration,
            route: window.location.pathname,
          },
        });
      }
    }
  });

  observer.observe({ type: 'longtask', buffered: true });
}

Dynamic Import Tracking

// Track lazy-loaded chunks
async function trackedImport<T>(
  importFn: () => Promise<T>,
  chunkName: string
): Promise<T> {
  const startTime = performance.now();

  try {
    const module = await importFn();
    const duration = performance.now() - startTime;

    trackChunkLoad({
      chunk_name: chunkName,
      duration_ms: duration,
      success: true,
    });

    return module;
  } catch (error) {
    trackChunkLoad({
      chunk_name: chunkName,
      success: false,
      error_type: error instanceof Error ? error.name : 'unknown',
    });
    throw error;
  }
}

// Usage
const HeavyComponent = lazy(() =>
  trackedImport(
    () => import('./HeavyComponent'),
    'HeavyComponent'
  )
);

CI/CD Integration

Size Limit

// package.json
{
  "size-limit": [
    {
      "path": "dist/**/*.js",
      "limit": "200 KB"
    },
    {
      "path": "dist/vendor*.js",
      "limit": "100 KB"
    }
  ]
}

bundlewatch

// bundlewatch.config.json
{
  "files": [
    {
      "path": "./dist/main*.js",
      "maxSize": "150kB"
    },
    {
      "path": "./dist/vendor*.js",
      "maxSize": "100kB"
    }
  ],
  "ci": {
    "trackBranches": ["main"],
    "repoBranchBase": "main"
  }
}

Third-Party Script Tracking

function trackThirdPartyScripts() {
  const entries = performance.getEntriesByType('resource') as PerformanceResourceTiming[];

  const thirdParty = entries.filter((entry) => {
    const url = new URL(entry.name);
    return url.hostname !== window.location.hostname;
  });

  const summary = {
    count: thirdParty.length,
    total_size_bytes: thirdParty.reduce((sum, e) => sum + e.transferSize, 0),
    total_duration_ms: thirdParty.reduce((sum, e) => sum + e.duration, 0),
    scripts: thirdParty.map((e) => ({
      url: e.name,
      size_bytes: e.transferSize,
      duration_ms: e.duration,
    })),
  };

  trackThirdPartyImpact(summary);
}

Optimization Strategies

| Strategy | Impact | Implementation | |----------|--------|----------------| | Code splitting | High | Route-based chunks | | Tree shaking | High | ES modules, sideEffects | | Dynamic imports | High | Lazy load non-critical | | Compression | High | Brotli/gzip | | Modern/legacy | Medium | module/nomodule | | Vendor chunking | Medium | Manual chunks | | Preload critical | Medium | modulepreload |

Anti-Patterns

  • Loading entire SDK in main bundle
  • Not code-splitting routes
  • Importing entire lodash/moment
  • Missing tree-shaking (CommonJS)
  • Not monitoring bundle size in CI
  • Third-party scripts without budget

Related Skills

  • See skills/core-web-vitals for LCP/INP impact
  • See skills/hydration-performance for JS impact on hydration
  • See skills/synthetic-monitoring for lab testing

References

  • references/performance.md - Performance budgets
  • references/frameworks/*.md - Framework-specific optimization