web-insight-analyzer
v1.0.0
Published
Production-grade library for analyzing web performance, Web Vitals, network requests, and resource coverage
Maintainers
Readme
web-insight-analyzer
A production-grade TypeScript library for comprehensive web performance analysis. Analyze Web Vitals, track network requests, identify unused CSS/JavaScript, and extract resource details with a clean, type-safe API.
Features
- 🎯 Web Vitals Metrics: LCP, CLS, INP, FCP measurement
- 📊 Network Analysis: Track all resources during initial page load
- 🎨 CSS Coverage: Detect unused CSS rules and calculate coverage percentage
- ⚙️ JavaScript Coverage: Track unused JavaScript code
- 🖼️ Image Analysis: Extract image details, responsiveness, and lazy-loading status
- ⚡ Critical Resources: Automatic identification of critical vs. non-critical resources
- � Intelligent Recommendations: Actionable performance improvement suggestions with code examples
- 🔌 Browser Abstraction: Pluggable browser adapter (Playwright included)
- 📝 CLI Tool: Ready-to-use command-line interface with colored output
- 🚀 Performance: Single browser session, no duplicate page loads
- 🛡️ Type-Safe: 100% TypeScript with strict mode, zero
anytypes - ✅ Fully Tested: Comprehensive unit and integration tests (77+ tests)
- 🔍 Dev Mode: Watch local development with real-time re-analysis on file changes
- 📡 Live Overlay: Inject lightweight Web Vitals display directly in browser (<10KB)
- ⚙️ Vite Plugin: Automatic analysis integration for Vite dev servers
- 🔄 Dev/Prod Comparison: Compare metrics between local and production builds
Installation
npm install web-insight-analyzer
# or with yarn
yarn add web-insight-analyzer
# or with pnpm
pnpm add web-insight-analyzerBrowser Installation
The package includes Playwright for browser automation. Browser binaries are automatically installed during the postinstall phase. If you need to manually install them:
npx playwright installThis downloads Chromium, Firefox, and WebKit (~400MB). You can install specific browsers:
# Install only Chromium (minimal ~200MB)
npx playwright install chromium
# Install only Firefox
npx playwright install firefox
# Install only WebKit
npx playwright install webkitNote: If you see Failed to launch browser error, run npx playwright install to download the browser binaries.
Quick Start
Programmatic API
import { analyzePage } from 'web-insight-analyzer';
const result = await analyzePage('https://example.com');
console.log('Web Vitals:', result.webVitals);
console.log('Total Resources:', result.resources.length);
console.log('Unused CSS:', result.unusedCss.unusedPercentage + '%');
console.log('Images:', result.images.length);CLI Usage
# Basic analysis
npx web-insight-analyzer https://example.com
# Output as JSON
npx web-insight-analyzer https://example.com --json
# Custom viewport
npx web-insight-analyzer https://example.com --viewport=1920x1080
# Visible browser
npx web-insight-analyzer https://example.com --headless=false
# Custom timeout
npx web-insight-analyzer https://example.com --timeout=60000
# Inject live Web Vitals overlay
npx web-insight-analyzer https://example.com --overlay
# Wait for specific element before analyzing
npx web-insight-analyzer https://example.com --wait-selector=".app-loaded"
# Watch local development and re-analyze on changes
npx web-insight-analyzer dev http://localhost:3000
# Compare local vs production
npx web-insight-analyzer compare http://localhost:3000 https://example.com
# Get detailed command help
npx web-insight-analyzer help [command]API Reference
analyzePage(url, options?)
Main entry point for analyzing a web page.
Parameters:
url: string- URL to analyzeoptions?: AnalyzeOptions- Optional configuration
Returns: Promise<AnalyzeResult>
Example:
const result = await analyzePage('https://example.com', {
timeout: 30000,
headless: true,
viewportWidth: 1280,
viewportHeight: 720,
waitUntil: 'networkidle'
});AnalyzeResult Type
interface AnalyzeResult {
url: string;
duration: number; // milliseconds
webVitals: WebVitals;
resources: Resource[];
unusedCss: CssCoverageReport;
unusedJs: JsCoverageReport;
images: ImageResource[];
}WebVitals Type
interface WebVitals {
lcp: number; // Largest Contentful Paint (ms)
cls: number; // Cumulative Layout Shift
inp: number; // Interaction to Next Paint (ms)
fcp: number; // First Contentful Paint (ms)
}Resource Type
interface Resource {
url: string;
mimeType: string;
size: number;
type: ResourceType; // 'script' | 'stylesheet' | 'image' | 'font' | etc
critical: boolean;
duration: number; // download time in ms
statusCode: number;
used: boolean;
}CssCoverageReport Type
interface CssCoverageReport {
unusedPercentage: number;
totalBytes: number;
unusedBytes: number;
unusedSelectors: string[];
files: CssCoverageFile[];
}JsCoverageReport Type
interface JsCoverageReport {
unusedPercentage: number;
totalBytes: number;
unusedBytes: number;
files: JsCoverageFile[];
}ImageResource Type
interface ImageResource {
url: string;
width: number;
height: number;
size: number;
mimeType: string;
isResponsive: boolean;
isLazy: boolean;
loadTime: number;
}AnalyzeOptions Type
interface AnalyzeOptions {
timeout?: number; // milliseconds (default: 30000)
headless?: boolean; // default: true
viewportWidth?: number; // default: 1280
viewportHeight?: number; // default: 720
waitUntil?: 'load' | 'domcontentloaded' | 'networkidle' | 'commit';
waitSelector?: string; // CSS selector to wait for before analyzing
userAgent?: string;
headers?: Record<string, string>;
injectOverlay?: boolean; // Inject Web Vitals overlay (default: false)
devMode?: boolean; // Flag for future dev-specific features
}New Development Options:
waitSelector- CSS selector to wait for (useful for SPAs and dynamic content)injectOverlay- Enable live Web Vitals display in browserdevMode- Reserved for future dev-specific features
Architecture
The package follows clean architecture principles with dependency injection:
src/
├── core/
│ ├── analyzer.ts # Main orchestrator
│ ├── metrics.ts # Web Vitals collection
│ ├── coverage.ts # CSS/JS coverage analysis
│ └── network.ts # Network request tracking
├── adapters/
│ └── playwrightAdapter.ts # Playwright implementation
├── types/
│ └── index.ts # Type definitions
├── utils/
│ └── helpers.ts # Utility functions
├── cli/
│ └── index.ts # CLI implementation
└── index.ts # Public APIDependency Injection
The PageAnalyzer accepts a BrowserAdapter interface, allowing you to provide custom browser implementations:
import { PageAnalyzer } from 'web-insight-analyzer';
import { CustomBrowserAdapter } from './my-adapter';
const analyzer = new PageAnalyzer(new CustomBrowserAdapter());
const result = await analyzer.analyzePage('https://example.com');
await analyzer.close();Advanced Usage
Custom Browser Implementation
Implement the BrowserAdapter interface for alternative browsers:
import { BrowserAdapter, AnalyzeResult, AnalyzeOptions } from 'web-insight-analyzer';
class CustomAdapter implements BrowserAdapter {
async analyzePage(url: string, options?: AnalyzeOptions): Promise<AnalyzeResult> {
// Your custom implementation
}
async close(): Promise<void> {
// Cleanup
}
}Error Handling
import { analyzePage, AnalyzerError, ErrorCode } from 'web-insight-analyzer';
try {
const result = await analyzePage('https://example.com');
} catch (error) {
if (error instanceof AnalyzerError) {
console.error(`Error: ${error.message}`);
console.error(`Code: ${error.code}`);
if (error.code === ErrorCode.INVALID_URL) {
// Handle invalid URL
} else if (error.code === ErrorCode.TIMEOUT) {
// Handle timeout
}
}
}Batch Analysis
import { PageAnalyzer } from 'web-insight-analyzer';
import { createPlaywrightAdapter } from 'web-insight-analyzer';
const adapter = createPlaywrightAdapter();
const analyzer = new PageAnalyzer(adapter);
const urls = [
'https://example1.com',
'https://example2.com',
'https://example3.com'
];
try {
const results = await Promise.all(
urls.map(url => analyzer.analyzePage(url))
);
// Process results
results.forEach(result => {
console.log(`${result.url}: ${result.webVitals.lcp}ms LCP`);
});
} finally {
await analyzer.close();
}Performance Recommendations
The library includes an intelligent recommendation engine that generates actionable suggestions based on analysis results:
import { analyzePage, RecommendationEngine } from 'web-insight-analyzer';
const result = await analyzePage('https://example.com');
const recommendations = RecommendationEngine.generateRecommendations(result);
// Recommendations are sorted by severity (critical → info) and impact score
recommendations.forEach(rec => {
console.log(`[${rec.severity}] ${rec.title}`);
console.log(` Impact: ${rec.impact}/100`);
console.log(` Advice: ${rec.advice}`);
console.log(` Example: ${rec.example}`);
});Recommendation Categories
- Web Vitals Optimization: LCP, CLS, INP, FCP improvements
- CSS Coverage: Unused CSS elimination strategies
- JavaScript Optimization: Code splitting and lazy loading
- Resource Management: Render-blocking and large resource handling
- Image Optimization: Responsive images and lazy-loading
Severity Levels
critical- Immediate action required (e.g., LCP > 4s)high- Should be addressed soon (e.g., unused CSS > 50%)medium- Would improve performance (e.g., missing alt text)low- Nice-to-have optimizationinfo- Informational guidance
CLI Output
The CLI automatically displays the top 5 recommendations with severity color-coding:
npx web-insight-analyzer https://example.comOutput includes:
- Recommendation title and severity
- Impact score (50-100)
- Affected metrics (LCP, CLS, etc.)
- Detailed advice and code examples
Performance Considerations
- Single Session: The library uses a single browser context per analyzer instance
- No Duplicate Loads: Each page is loaded only once
- Network Idle Detection: Supports waiting for
networkidleevent - Timeout Handling: Configurable timeout with graceful degradation
- Resource Cleanup: Properly closes browser on completion
Development Features
Dev Mode - Watch and Re-analyze
Monitor your local development environment in real-time with automatic re-analysis on file changes:
# Watch local dev server and re-analyze on every change
npx web-insight-analyzer dev http://localhost:3000
# With custom viewport
npx web-insight-analyzer dev http://localhost:3000 --viewport=768x1024
# With extended timeout for slower builds
npx web-insight-analyzer dev http://localhost:5173 --timeout=60000The dev mode:
- Watches your current directory for file changes
- Re-runs analysis whenever files are modified
- Displays incremental results
- Gracefully handles SIGINT (Ctrl+C)
- Perfect for catching performance regressions during development
Live Web Vitals Overlay
Inject a lightweight, real-time Web Vitals display directly into your browser:
# Analyze with overlay injection
npx web-insight-analyzer https://example.com --overlay
# Programmatically
import { analyzePage, getOverlayScript } from 'web-insight-analyzer';
const result = await analyzePage('https://example.com', {
injectOverlay: true,
waitUntil: 'networkidle'
});The overlay displays:
- LCP (Largest Contentful Paint) - Target: < 2.5s
- FCP (First Contentful Paint) - Target: < 1.8s
- CLS (Cumulative Layout Shift) - Target: < 0.1
- INP (Interaction to Next Paint) - Target: < 200ms
Status colors:
- 🟢 Green: Good (within thresholds)
- 🟡 Yellow: Warning (near threshold)
- 🔴 Red: Poor (exceeds threshold)
The overlay is less than 10KB and includes:
- Real-time metric updates via PerformanceObserver
- Toggle button to hide/show
- Fixed positioning in top-right corner
- No impact on page performance
Dev/Prod Comparison
Compare performance metrics between your local development build and production:
# Compare local vs production
npx web-insight-analyzer compare http://localhost:3000 https://example.com
# Output as JSON for programmatic processing
npx web-insight-analyzer compare http://localhost:3000 https://example.com --jsonThe comparison shows:
- Side-by-side Web Vitals metrics
- Percentage changes (improvement/regression)
- Resource count and size differences
- CSS/JavaScript coverage comparison
- Image resource analysis
- Recommendation severity differences
Example output:
Performance Comparison Report
================================================================================
URLs:
Development: http://localhost:3000
Production: https://example.com
Web Vitals:
LCP: 2100ms (dev) → 1800ms (prod) 🟢 14.3% improvement
FCP: 900ms (dev) → 850ms (prod) 🟢 5.6% improvement
CLS: 0.05 (dev) → 0.03 (prod) 🟢 40% improvement
INP: 150ms (dev) → 120ms (prod) 🟢 20% improvement
Resources:
Total Count: 45 (dev) → 52 (prod)
Total Size: 2.1 MB (dev) → 2.3 MB (prod)
CSS Coverage: 85% (dev) → 92% (prod)
JavaScript Coverage: 78% (dev) → 88% (prod)
Images: 12 (dev) → 15 (prod)Programmatically:
import { analyzePage, calculateMetricsDiff, formatMetricsDiff } from 'web-insight-analyzer';
const devResult = await analyzePage('http://localhost:3000');
const prodResult = await analyzePage('https://example.com');
const diff = calculateMetricsDiff(devResult, prodResult);
const formatted = formatMetricsDiff(diff);
console.log(formatted);Vite Plugin Integration
Automatically inject analysis capabilities into your Vite dev server:
// vite.config.ts
import { defineConfig } from 'vite';
import { webInsightPlugin } from 'web-insight-analyzer/vite';
export default defineConfig({
plugins: [
webInsightPlugin({
enabled: true,
overlay: true,
autoAnalyze: false, // Manual trigger only
onAnalysis: (result) => {
console.log('Analysis complete:', result.webVitals);
}
})
]
});Plugin configuration:
enabled(boolean, default: true) - Enable/disable the pluginoverlay(boolean, default: true) - Inject overlay scriptautoAnalyze(boolean, default: false) - Auto-analyze on loadonAnalysis(callback) - Hook for analysis resultsport(number) - Custom analysis server port
The plugin:
- Injects overlay script into HTML
- Provides HMR support for full-reload triggers
- Zero configuration for basic usage
- All features opt-in, no performance degradation
Waiting Strategies
Control how long the analyzer waits for pages to fully load:
# Wait for network idle (default, safest option)
npx web-insight-analyzer https://example.com --wait-until=networkidle
# Wait for page load event
npx web-insight-analyzer https://example.com --wait-until=load
# Wait for specific element to appear
npx web-insight-analyzer https://example.com --wait-selector=".content-ready"
# Combination: wait until network idle OR selector appears
npx web-insight-analyzer https://example.com \
--wait-until=networkidle \
--wait-selector=".app-initialized"Programmatically:
const result = await analyzePage('https://example.com', {
waitUntil: 'networkidle', // 'load', 'domcontentloaded', 'networkidle'
waitSelector: '.page-ready', // CSS selector to wait for
timeout: 30000 // Timeout in milliseconds
});CLI Examples
# Analyze homepage
npx web-insight-analyzer https://github.com
# Get JSON output for scripting
npx web-insight-analyzer https://google.com --json | jq '.webVitals.lcp'
# Run with custom viewport (tablet size)
npx web-insight-analyzer https://example.com --viewport=768x1024
# Visible browser for debugging
npx web-insight-analyzer https://example.com --headless=false
# Extended timeout for slow pages
npx web-insight-analyzer https://slow-site.com --timeout=60000
# Dev workflow: analyze with overlay + wait for custom selector
npx web-insight-analyzer dev http://localhost:3000 --overlay --wait-selector=".app"
# Compare production performance
npx web-insight-analyzer compare http://localhost:3000 https://prod.example.com
# Help for specific command
npx web-insight-analyzer help devTesting
# Run all tests
npm test
# Run tests in watch mode
npm run test:watch
# Generate coverage report
npm run test:coverage
# Run specific test file
npm test -- helpers.test.tsBuilding
# Build to dist/
npm run build
# Clean build
npm run clean
# Type checking
npm run type-check
# Linting
npm run lint
# Format code
npm run formatRequirements
- Node.js >= 16.0.0
- TypeScript 5.3+
- Playwright (included as dependency)
Browser Support
Currently supports Chromium via Playwright. Other browsers can be supported through custom adapters.
Troubleshooting
Browser Launch Failed
Error: Failed to launch browser or Browser not found
Solution: Playwright browsers are not installed. Run:
npx playwright installThis automatically happens during npm install, but if you see this error, manually run the command above.
403 Forbidden / Access Denied
Error: statusCode: 403 in results with only document resource
Cause: Website is blocking Playwright browser due to bot detection (Cloudflare, WAF, etc.)
Solutions:
Use custom User-Agent:
npx web-insight-analyzer https://example.com --user-agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36"Use visible browser for testing:
npx web-insight-analyzer https://example.com --headless=falseTry with extended timeout:
npx web-insight-analyzer https://example.com --timeout=60000
Zero Metrics (LCP/FCP = 0ms)
Cause: Page didn't fully load before analysis completed
Solutions:
Use
networkidlewait strategy (default):npx web-insight-analyzer https://example.com --wait-until=networkidleWait for specific element:
npx web-insight-analyzer https://example.com --wait-selector=".main-content"Increase timeout:
npx web-insight-analyzer https://example.com --timeout=60000
Port Already in Use
Error: When using dev mode, port is already in use
Solution: The dev mode doesn't use ports; if you see this, restart your dev server or check for other processes using that port.
Out of Memory
Error: JavaScript heap out of memory or similar
Cause: Analyzing very large pages or many URLs in parallel
Solutions:
Increase Node.js memory:
node --max-old-space-size=4096 dist/cli/index.js https://example.comAnalyze URLs sequentially instead of in parallel
Close other applications to free up memory
Error Codes
INVALID_URL- Malformed URL providedTIMEOUT- Analysis exceeded timeout limitBROWSER_ERROR- Browser initialization failedPAGE_LOAD_FAILED- Unable to load the pageNETWORK_ERROR- Network request failedCDP_ERROR- Chrome DevTools Protocol error
Performance Metrics Guide
Web Vitals Interpretation
| Metric | Good | Needs Improvement | Poor | |--------|------|------------------|------| | LCP | < 2.5s | 2.5s - 4s | > 4s | | CLS | < 0.1 | 0.1 - 0.25 | > 0.25 | | INP | < 200ms | 200-500ms | > 500ms | | FCP | < 1.8s | 1.8s - 3s | > 3s |
Resource Prioritization
The library categorizes resources as critical or non-critical:
Critical Resources:
- Stylesheets (render-blocking)
- Inline scripts
- Early-loaded resources (< 100ms)
Non-Critical Resources:
- Async scripts
- Images
- Late-loading resources
Limitations
- Coverage Analysis: Requires Chrome/Chromium. Provides best-effort analysis; exact coverage may vary
- Network Simulation: No built-in network throttling (use Playwright's network interception)
- SPAs: Designed for initial page load; SPA navigation tracking requires custom implementation
- JavaScript Execution: Only tracks usage during initial load and network idle
Contributing
Contributions are welcome! Please ensure:
- TypeScript strict mode compliance
- Zero
anytypes - Full type coverage
- All tests pass
- Code formatted with Prettier
License
MIT License - see LICENSE file for details
Roadmap
- [x] Dev mode with file watching
- [x] Live Web Vitals overlay (<10KB)
- [x] Dev vs production comparison
- [x] Vite plugin integration
- [x] Selector-based waiting strategy
- [ ] Network throttling profiles
- [ ] Lighthouse integration
- [ ] SPA navigation tracking
- [ ] Video/WebP performance metrics
- [ ] Core Web Vitals v2 support
- [ ] Firefox support
- [ ] Safari support
- [ ] Regression detection
- [ ] CI/CD integration plugins
Support
For issues, questions, or feature requests, please open an issue on GitHub.
Made with ❤️ for web performance enthusiasts
