UNPKG

@code-zetta/ng-profiler

Version:

A tiny in-app profiler overlay for Angular that works in both zoned and zoneless applications

351 lines (341 loc) 10.9 kB
import * as i0 from '@angular/core'; import { InjectionToken, ApplicationRef, OnInit, OnDestroy, ElementRef, NgZone, ModuleWithProviders, Provider } from '@angular/core'; import * as i1 from '@angular/common'; import { Observable } from 'rxjs'; interface NgProfilerConfig { /** Enable profiler in production (default: false) */ enableInProduction?: boolean; /** Hotkey to toggle overlay (default: 'Ctrl+Shift+P') */ hotkey?: string; /** Position of overlay (default: 'top-right') */ position?: 'top-left' | 'top-right' | 'bottom-left' | 'bottom-right'; /** Threshold for render count warnings (default: 10) */ renderCountThreshold?: number; /** Threshold for frame duration warnings in ms (default: 16.67) */ frameDurationThreshold?: number; /** Enable heatmap outlines (default: true) */ enableHeatmap?: boolean; /** Enable performance measurement (default: true) */ enableMeasurement?: boolean; } declare const NG_PROFILER_CONFIG: InjectionToken<NgProfilerConfig>; interface ProfilerStats { /** Last tick/frame duration in ms */ lastFrameDuration: number; /** Average frame duration in ms */ averageFrameDuration: number; /** Total number of frames measured */ frameCount: number; /** Top components by render count */ topComponents: ComponentRenderStats[]; /** Timestamp of last measurement */ lastMeasurement: number; /** Performance recommendations */ recommendations?: PerformanceRecommendation[]; } interface ComponentRenderStats { /** Component name or element tag */ name: string; /** Number of renders */ renderCount: number; /** Severity level */ severity: 'low' | 'medium' | 'high'; /** Element reference for heatmap */ element?: HTMLElement; } interface FrameMeasurement { duration: number; timestamp: number; } interface PerformanceRecommendation { id: string; type: 'warning' | 'error' | 'info' | 'optimization'; title: string; description: string; severity: 'low' | 'medium' | 'high' | 'critical'; category: 'performance' | 'memory' | 'rendering' | 'best-practice'; suggestions: string[]; impact: string; priority: number; } declare global { interface Window { Zone?: any; } } declare class RecommendationService { /** * Analyze performance data and generate recommendations */ analyzePerformance(stats: ProfilerStats): PerformanceRecommendation[]; /** * Analyze frame performance issues */ private analyzeFramePerformance; /** * Analyze component render issues */ private analyzeComponentRenders; /** * Analyze component patterns and architecture */ private analyzeComponentPatterns; /** * Analyze template optimization opportunities */ private analyzeTemplateOptimization; /** * Analyze memory usage patterns */ private analyzeMemoryUsage; /** * Analyze best practices and advanced optimizations */ private analyzeBestPractices; /** * Analyze network performance patterns */ private analyzeNetworkPerformance; /** * Analyze bundle optimization opportunities */ private analyzeBundleOptimization; /** * Analyze state management patterns */ private analyzeStateManagement; /** * Get recommendation by ID */ getRecommendationById(id: string, stats: ProfilerStats): PerformanceRecommendation | null; /** * Get recommendations by category */ getRecommendationsByCategory(category: string, stats: ProfilerStats): PerformanceRecommendation[]; /** * Get critical recommendations only */ getCriticalRecommendations(stats: ProfilerStats): PerformanceRecommendation[]; /** * Check if performance is within acceptable thresholds */ isPerformanceAcceptable(stats: ProfilerStats): boolean; /** * Get performance score (0-100) */ getPerformanceScore(stats: ProfilerStats): number; /** * Get performance health status */ getPerformanceHealth(stats: ProfilerStats): 'excellent' | 'good' | 'fair' | 'poor' | 'critical'; /** * Get performance summary */ getPerformanceSummary(stats: ProfilerStats): { score: number; health: string; acceptable: boolean; criticalIssues: number; warnings: number; }; static ɵfac: i0.ɵɵFactoryDeclaration<RecommendationService, never>; static ɵprov: i0.ɵɵInjectableDeclaration<RecommendationService>; } declare class ProfilerStore { private recommendationService; private renderCounts; private elementMap; private frameMeasurements; private maxFrameHistory; private isPaused; constructor(recommendationService: RecommendationService); private statsSubject; stats$: Observable<ProfilerStats>; /** * Increment render count for a component */ incrementRenderCount(name: string, element?: HTMLElement): void; /** * Add frame measurement */ addFrameMeasurement(duration: number): void; /** * Get severity level based on render count */ private getSeverity; /** * Update statistics */ private updateStats; /** * Reset all statistics */ reset(): void; /** * Export current statistics as JSON */ exportStats(): string; /** * Get current render count for a component */ getRenderCount(name: string): number; /** * Get all render counts */ getAllRenderCounts(): Map<string, number>; /** * Pause render counting */ pauseRenderCounting(): void; /** * Resume render counting */ resumeRenderCounting(): void; static ɵfac: i0.ɵɵFactoryDeclaration<ProfilerStore, never>; static ɵprov: i0.ɵɵInjectableDeclaration<ProfilerStore>; } declare class NgProfilerService { private appRef; private profilerStore; private config; private isEnabled; private isZoned; private originalTick; private frameStartTime; private longTaskObserver; private animationFrameId; constructor(appRef: ApplicationRef, profilerStore: ProfilerStore, config: NgProfilerConfig); /** * Initialize the profiler */ initialize(): void; /** * Check if profiler should be enabled */ private shouldEnable; /** * Check if running in production */ private isProduction; /** * Detect if Zone.js is present */ private detectZone; /** * Patch ApplicationRef.tick() for zoned applications */ private patchApplicationRef; /** * Setup measurement for zoneless applications */ private setupZonelessMeasurement; /** * Setup hotkey listener */ private setupHotkey; /** * Toggle overlay visibility */ toggleOverlay(): void; /** * Cleanup resources */ destroy(): void; /** * Get current configuration */ getConfig(): NgProfilerConfig; /** * Check if profiler is enabled */ isProfilerEnabled(): boolean; /** * Check if running in zoned mode */ isZonedMode(): boolean; /** * Pause profiling temporarily */ pauseProfiling(): void; /** * Resume profiling */ resumeProfiling(): void; static ɵfac: i0.ɵɵFactoryDeclaration<NgProfilerService, never>; static ɵprov: i0.ɵɵInjectableDeclaration<NgProfilerService>; } declare class NgProfilerOverlayComponent implements OnInit, OnDestroy { private profilerStore; profilerService: NgProfilerService; isVisible: boolean; stats: ProfilerStats; private subscription; position: 'top-left' | 'top-right' | 'bottom-left' | 'bottom-right'; constructor(profilerStore: ProfilerStore, profilerService: NgProfilerService); ngOnInit(): void; ngOnDestroy(): void; onEscapeKey(): void; toggleVisibility(): void; resetStats(): void; exportStats(): void; exportPDF(): Promise<void>; trackByComponent(index: number, component: ComponentRenderStats): string; trackByRecommendation(index: number, recommendation: PerformanceRecommendation): string; showAllRecommendations(): void; static ɵfac: i0.ɵɵFactoryDeclaration<NgProfilerOverlayComponent, never>; static ɵcmp: i0.ɵɵComponentDeclaration<NgProfilerOverlayComponent, "codezetta-ng-profiler-overlay", never, {}, {}, never, never, true, never>; } declare class NgProfilerDirective implements OnInit, OnDestroy { private elementRef; private profilerStore; private ngZone; componentName?: string; private renderCount; private elementName; private isDestroyed; private observer; private resizeObserver; constructor(elementRef: ElementRef<HTMLElement>, profilerStore: ProfilerStore, ngZone: NgZone); ngOnInit(): void; ngOnDestroy(): void; /** * Setup passive observation using MutationObserver and ResizeObserver */ private setupPassiveObservation; /** * Cleanup observers to prevent memory leaks */ private cleanupObservers; /** * Get component name for tracking */ private getComponentName; /** * Update heatmap attribute based on render count */ private updateHeatmapAttribute; /** * Get severity level based on render count */ private getSeverityLevel; /** * Get current render count */ getRenderCount(): number; static ɵfac: i0.ɵɵFactoryDeclaration<NgProfilerDirective, never>; static ɵdir: i0.ɵɵDirectiveDeclaration<NgProfilerDirective, "[codezettaNgProfiler]", never, { "componentName": { "alias": "codezettaNgProfiler"; "required": false; }; }, {}, never, never, true, never>; } declare class NgProfilerModule { static forRoot(config?: NgProfilerConfig): ModuleWithProviders<NgProfilerModule>; static ɵfac: i0.ɵɵFactoryDeclaration<NgProfilerModule, never>; static ɵmod: i0.ɵɵNgModuleDeclaration<NgProfilerModule, never, [typeof i1.CommonModule, typeof NgProfilerOverlayComponent, typeof NgProfilerDirective], [typeof NgProfilerOverlayComponent, typeof NgProfilerDirective]>; static ɵinj: i0.ɵɵInjectorDeclaration<NgProfilerModule>; } /** * Provides the NgProfiler services for standalone components * @param config Optional configuration for the profiler * @returns Array of providers for dependency injection */ declare function provideNgProfiler(config?: NgProfilerConfig): Provider[]; export { NG_PROFILER_CONFIG, NgProfilerDirective, NgProfilerModule, NgProfilerOverlayComponent, NgProfilerService, ProfilerStore, RecommendationService, provideNgProfiler }; export type { ComponentRenderStats, FrameMeasurement, NgProfilerConfig, PerformanceRecommendation, ProfilerStats };