omgkit 2.0.6 → 2.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (33) hide show
  1. package/package.json +6 -3
  2. package/plugin/agents/architect.md +357 -43
  3. package/plugin/agents/code-reviewer.md +481 -22
  4. package/plugin/agents/debugger.md +397 -30
  5. package/plugin/agents/docs-manager.md +431 -23
  6. package/plugin/agents/fullstack-developer.md +395 -34
  7. package/plugin/agents/git-manager.md +438 -20
  8. package/plugin/agents/oracle.md +329 -53
  9. package/plugin/agents/planner.md +275 -32
  10. package/plugin/agents/researcher.md +343 -21
  11. package/plugin/agents/scout.md +423 -18
  12. package/plugin/agents/sprint-master.md +418 -48
  13. package/plugin/agents/tester.md +551 -26
  14. package/plugin/skills/backend/api-architecture/SKILL.md +857 -0
  15. package/plugin/skills/backend/caching-strategies/SKILL.md +755 -0
  16. package/plugin/skills/backend/event-driven-architecture/SKILL.md +753 -0
  17. package/plugin/skills/backend/real-time-systems/SKILL.md +635 -0
  18. package/plugin/skills/databases/database-optimization/SKILL.md +571 -0
  19. package/plugin/skills/devops/monorepo-management/SKILL.md +595 -0
  20. package/plugin/skills/devops/observability/SKILL.md +622 -0
  21. package/plugin/skills/devops/performance-profiling/SKILL.md +905 -0
  22. package/plugin/skills/frontend/advanced-ui-design/SKILL.md +426 -0
  23. package/plugin/skills/integrations/ai-integration/SKILL.md +730 -0
  24. package/plugin/skills/integrations/payment-integration/SKILL.md +735 -0
  25. package/plugin/skills/methodology/problem-solving/SKILL.md +355 -0
  26. package/plugin/skills/methodology/research-validation/SKILL.md +668 -0
  27. package/plugin/skills/methodology/sequential-thinking/SKILL.md +260 -0
  28. package/plugin/skills/mobile/mobile-development/SKILL.md +756 -0
  29. package/plugin/skills/security/security-hardening/SKILL.md +633 -0
  30. package/plugin/skills/tools/document-processing/SKILL.md +916 -0
  31. package/plugin/skills/tools/image-processing/SKILL.md +748 -0
  32. package/plugin/skills/tools/mcp-development/SKILL.md +883 -0
  33. package/plugin/skills/tools/media-processing/SKILL.md +831 -0
@@ -0,0 +1,905 @@
1
+ ---
2
+ name: performance-profiling
3
+ description: Browser automation, Chrome DevTools Protocol, Lighthouse audits, and Core Web Vitals optimization
4
+ category: devops
5
+ triggers:
6
+ - performance profiling
7
+ - lighthouse audit
8
+ - core web vitals
9
+ - page speed
10
+ - chrome devtools
11
+ - performance optimization
12
+ - bundle analysis
13
+ ---
14
+
15
+ # Performance Profiling
16
+
17
+ Master **browser performance profiling** using Chrome DevTools Protocol, Lighthouse, and Core Web Vitals monitoring. This skill enables automated performance audits, bottleneck identification, and optimization guidance.
18
+
19
+ ## Purpose
20
+
21
+ Performance directly impacts user experience and business metrics:
22
+
23
+ - Run automated Lighthouse audits with detailed analysis
24
+ - Monitor Core Web Vitals (LCP, FID, CLS, INP)
25
+ - Identify JavaScript performance bottlenecks
26
+ - Analyze network waterfalls and resource loading
27
+ - Detect memory leaks and optimize memory usage
28
+ - Create performance budgets and regression testing
29
+
30
+ ## Features
31
+
32
+ ### 1. Lighthouse Automation
33
+
34
+ ```typescript
35
+ import lighthouse from 'lighthouse';
36
+ import * as chromeLauncher from 'chrome-launcher';
37
+
38
+ interface LighthouseConfig {
39
+ url: string;
40
+ categories?: ('performance' | 'accessibility' | 'best-practices' | 'seo')[];
41
+ device?: 'mobile' | 'desktop';
42
+ throttling?: ThrottlingConfig;
43
+ }
44
+
45
+ interface LighthouseResult {
46
+ scores: Record<string, number>;
47
+ metrics: PerformanceMetrics;
48
+ opportunities: Opportunity[];
49
+ diagnostics: Diagnostic[];
50
+ }
51
+
52
+ // Run Lighthouse audit
53
+ async function runLighthouseAudit(config: LighthouseConfig): Promise<LighthouseResult> {
54
+ const chrome = await chromeLauncher.launch({ chromeFlags: ['--headless'] });
55
+
56
+ try {
57
+ const options = {
58
+ port: chrome.port,
59
+ output: 'json',
60
+ onlyCategories: config.categories || ['performance'],
61
+ formFactor: config.device || 'mobile',
62
+ throttling: config.throttling || {
63
+ rttMs: 150,
64
+ throughputKbps: 1638,
65
+ cpuSlowdownMultiplier: 4,
66
+ },
67
+ };
68
+
69
+ const result = await lighthouse(config.url, options);
70
+ const lhr = result?.lhr;
71
+
72
+ if (!lhr) throw new Error('Lighthouse failed to generate report');
73
+
74
+ return {
75
+ scores: {
76
+ performance: lhr.categories.performance?.score ?? 0,
77
+ accessibility: lhr.categories.accessibility?.score ?? 0,
78
+ bestPractices: lhr.categories['best-practices']?.score ?? 0,
79
+ seo: lhr.categories.seo?.score ?? 0,
80
+ },
81
+ metrics: extractMetrics(lhr),
82
+ opportunities: extractOpportunities(lhr),
83
+ diagnostics: extractDiagnostics(lhr),
84
+ };
85
+ } finally {
86
+ await chrome.kill();
87
+ }
88
+ }
89
+
90
+ // Extract key metrics
91
+ function extractMetrics(lhr: LH.Result): PerformanceMetrics {
92
+ const audits = lhr.audits;
93
+
94
+ return {
95
+ // Core Web Vitals
96
+ lcp: {
97
+ value: audits['largest-contentful-paint']?.numericValue ?? 0,
98
+ score: audits['largest-contentful-paint']?.score ?? 0,
99
+ displayValue: audits['largest-contentful-paint']?.displayValue ?? '',
100
+ },
101
+ fid: {
102
+ value: audits['max-potential-fid']?.numericValue ?? 0,
103
+ score: audits['max-potential-fid']?.score ?? 0,
104
+ displayValue: audits['max-potential-fid']?.displayValue ?? '',
105
+ },
106
+ cls: {
107
+ value: audits['cumulative-layout-shift']?.numericValue ?? 0,
108
+ score: audits['cumulative-layout-shift']?.score ?? 0,
109
+ displayValue: audits['cumulative-layout-shift']?.displayValue ?? '',
110
+ },
111
+
112
+ // Additional metrics
113
+ fcp: audits['first-contentful-paint']?.numericValue ?? 0,
114
+ ttfb: audits['server-response-time']?.numericValue ?? 0,
115
+ tti: audits['interactive']?.numericValue ?? 0,
116
+ tbt: audits['total-blocking-time']?.numericValue ?? 0,
117
+ speedIndex: audits['speed-index']?.numericValue ?? 0,
118
+ };
119
+ }
120
+
121
+ // Extract optimization opportunities
122
+ function extractOpportunities(lhr: LH.Result): Opportunity[] {
123
+ const opportunityAudits = [
124
+ 'render-blocking-resources',
125
+ 'unused-css-rules',
126
+ 'unused-javascript',
127
+ 'modern-image-formats',
128
+ 'offscreen-images',
129
+ 'unminified-css',
130
+ 'unminified-javascript',
131
+ 'efficient-animated-content',
132
+ 'duplicated-javascript',
133
+ ];
134
+
135
+ return opportunityAudits
136
+ .map(id => lhr.audits[id])
137
+ .filter(audit => audit && audit.score !== null && audit.score < 1)
138
+ .map(audit => ({
139
+ id: audit.id,
140
+ title: audit.title,
141
+ description: audit.description,
142
+ savings: audit.details?.overallSavingsMs ?? 0,
143
+ items: audit.details?.items ?? [],
144
+ }))
145
+ .sort((a, b) => b.savings - a.savings);
146
+ }
147
+ ```
148
+
149
+ ### 2. Core Web Vitals Monitoring
150
+
151
+ ```typescript
152
+ import { onLCP, onFID, onCLS, onINP, onTTFB } from 'web-vitals';
153
+
154
+ interface WebVitalsReport {
155
+ lcp: VitalMetric;
156
+ fid: VitalMetric;
157
+ cls: VitalMetric;
158
+ inp: VitalMetric;
159
+ ttfb: VitalMetric;
160
+ }
161
+
162
+ interface VitalMetric {
163
+ value: number;
164
+ rating: 'good' | 'needs-improvement' | 'poor';
165
+ entries: PerformanceEntry[];
166
+ }
167
+
168
+ // Real User Monitoring (RUM) setup
169
+ function initWebVitalsMonitoring(onReport: (report: WebVitalsReport) => void): void {
170
+ const metrics: Partial<WebVitalsReport> = {};
171
+
172
+ const reportIfComplete = () => {
173
+ if (metrics.lcp && metrics.fid && metrics.cls && metrics.inp && metrics.ttfb) {
174
+ onReport(metrics as WebVitalsReport);
175
+ }
176
+ };
177
+
178
+ onLCP((metric) => {
179
+ metrics.lcp = {
180
+ value: metric.value,
181
+ rating: metric.rating,
182
+ entries: metric.entries,
183
+ };
184
+ reportIfComplete();
185
+ });
186
+
187
+ onFID((metric) => {
188
+ metrics.fid = {
189
+ value: metric.value,
190
+ rating: metric.rating,
191
+ entries: metric.entries,
192
+ };
193
+ reportIfComplete();
194
+ });
195
+
196
+ onCLS((metric) => {
197
+ metrics.cls = {
198
+ value: metric.value,
199
+ rating: metric.rating,
200
+ entries: metric.entries,
201
+ };
202
+ reportIfComplete();
203
+ });
204
+
205
+ onINP((metric) => {
206
+ metrics.inp = {
207
+ value: metric.value,
208
+ rating: metric.rating,
209
+ entries: metric.entries,
210
+ };
211
+ reportIfComplete();
212
+ });
213
+
214
+ onTTFB((metric) => {
215
+ metrics.ttfb = {
216
+ value: metric.value,
217
+ rating: metric.rating,
218
+ entries: metric.entries,
219
+ };
220
+ reportIfComplete();
221
+ });
222
+ }
223
+
224
+ // Web Vitals thresholds
225
+ const WEB_VITALS_THRESHOLDS = {
226
+ LCP: { good: 2500, poor: 4000 }, // milliseconds
227
+ FID: { good: 100, poor: 300 }, // milliseconds
228
+ CLS: { good: 0.1, poor: 0.25 }, // score
229
+ INP: { good: 200, poor: 500 }, // milliseconds
230
+ TTFB: { good: 800, poor: 1800 }, // milliseconds
231
+ };
232
+
233
+ // Analyze and provide recommendations
234
+ function analyzeWebVitals(report: WebVitalsReport): VitalsAnalysis {
235
+ const issues: VitalIssue[] = [];
236
+
237
+ // LCP analysis
238
+ if (report.lcp.rating !== 'good') {
239
+ const lcpElement = report.lcp.entries[0]?.element;
240
+ issues.push({
241
+ metric: 'LCP',
242
+ value: report.lcp.value,
243
+ rating: report.lcp.rating,
244
+ element: lcpElement,
245
+ recommendations: getLCPRecommendations(report.lcp, lcpElement),
246
+ });
247
+ }
248
+
249
+ // CLS analysis
250
+ if (report.cls.rating !== 'good') {
251
+ const clsSources = report.cls.entries.flatMap(
252
+ entry => (entry as LayoutShift).sources || []
253
+ );
254
+ issues.push({
255
+ metric: 'CLS',
256
+ value: report.cls.value,
257
+ rating: report.cls.rating,
258
+ sources: clsSources,
259
+ recommendations: getCLSRecommendations(clsSources),
260
+ });
261
+ }
262
+
263
+ // INP analysis
264
+ if (report.inp.rating !== 'good') {
265
+ issues.push({
266
+ metric: 'INP',
267
+ value: report.inp.value,
268
+ rating: report.inp.rating,
269
+ recommendations: getINPRecommendations(report.inp),
270
+ });
271
+ }
272
+
273
+ return {
274
+ overallRating: calculateOverallRating(report),
275
+ issues,
276
+ score: calculateVitalsScore(report),
277
+ };
278
+ }
279
+
280
+ // LCP optimization recommendations
281
+ function getLCPRecommendations(metric: VitalMetric, element?: Element): string[] {
282
+ const recommendations: string[] = [];
283
+
284
+ if (element?.tagName === 'IMG') {
285
+ recommendations.push(
286
+ 'Add fetchpriority="high" to the LCP image',
287
+ 'Preload the LCP image: <link rel="preload" as="image" href="...">',
288
+ 'Use modern image formats (WebP, AVIF)',
289
+ 'Ensure image is properly sized (no layout shift)',
290
+ );
291
+ }
292
+
293
+ if (metric.value > 4000) {
294
+ recommendations.push(
295
+ 'Reduce server response time (TTFB)',
296
+ 'Eliminate render-blocking resources',
297
+ 'Consider server-side rendering for critical content',
298
+ );
299
+ }
300
+
301
+ recommendations.push(
302
+ 'Minimize critical CSS',
303
+ 'Use efficient cache policy for static assets',
304
+ 'Consider using a CDN',
305
+ );
306
+
307
+ return recommendations;
308
+ }
309
+ ```
310
+
311
+ ### 3. Chrome DevTools Protocol
312
+
313
+ ```typescript
314
+ import CDP from 'chrome-remote-interface';
315
+
316
+ interface PerformanceTrace {
317
+ timelineEvents: TimelineEvent[];
318
+ networkRequests: NetworkRequest[];
319
+ jsProfile: CPUProfile;
320
+ heapSnapshot: HeapSnapshot;
321
+ }
322
+
323
+ // Connect to Chrome DevTools
324
+ async function connectToDevTools(port: number = 9222): Promise<CDP.Client> {
325
+ const client = await CDP({ port });
326
+
327
+ // Enable required domains
328
+ await Promise.all([
329
+ client.Page.enable(),
330
+ client.Network.enable(),
331
+ client.Performance.enable(),
332
+ client.Profiler.enable(),
333
+ client.HeapProfiler.enable(),
334
+ ]);
335
+
336
+ return client;
337
+ }
338
+
339
+ // Capture performance trace
340
+ async function capturePerformanceTrace(
341
+ client: CDP.Client,
342
+ url: string
343
+ ): Promise<PerformanceTrace> {
344
+ const networkRequests: NetworkRequest[] = [];
345
+ const timelineEvents: TimelineEvent[] = [];
346
+
347
+ // Collect network requests
348
+ client.Network.requestWillBeSent(params => {
349
+ networkRequests.push({
350
+ requestId: params.requestId,
351
+ url: params.request.url,
352
+ method: params.request.method,
353
+ timestamp: params.timestamp,
354
+ type: params.type,
355
+ });
356
+ });
357
+
358
+ client.Network.responseReceived(params => {
359
+ const request = networkRequests.find(r => r.requestId === params.requestId);
360
+ if (request) {
361
+ request.status = params.response.status;
362
+ request.mimeType = params.response.mimeType;
363
+ request.encodedDataLength = params.response.encodedDataLength;
364
+ }
365
+ });
366
+
367
+ // Start tracing
368
+ await client.Tracing.start({
369
+ categories: [
370
+ 'devtools.timeline',
371
+ 'v8.execute',
372
+ 'blink.user_timing',
373
+ 'loading',
374
+ 'painting',
375
+ ].join(','),
376
+ });
377
+
378
+ // Navigate to page
379
+ await client.Page.navigate({ url });
380
+ await client.Page.loadEventFired();
381
+
382
+ // Wait for network idle
383
+ await waitForNetworkIdle(client);
384
+
385
+ // Stop tracing
386
+ const { value: traceData } = await client.Tracing.tracingComplete();
387
+
388
+ // Capture JS profile
389
+ await client.Profiler.start();
390
+ await new Promise(r => setTimeout(r, 2000)); // Profile for 2 seconds
391
+ const { profile: jsProfile } = await client.Profiler.stop();
392
+
393
+ // Capture heap snapshot
394
+ const heapChunks: string[] = [];
395
+ client.HeapProfiler.addHeapSnapshotChunk(({ chunk }) => heapChunks.push(chunk));
396
+ await client.HeapProfiler.takeHeapSnapshot();
397
+ const heapSnapshot = JSON.parse(heapChunks.join(''));
398
+
399
+ return {
400
+ timelineEvents: parseTraceData(traceData),
401
+ networkRequests,
402
+ jsProfile,
403
+ heapSnapshot,
404
+ };
405
+ }
406
+
407
+ // Analyze network waterfall
408
+ function analyzeNetworkWaterfall(requests: NetworkRequest[]): WaterfallAnalysis {
409
+ const sorted = [...requests].sort((a, b) => a.timestamp - b.timestamp);
410
+ const totalTime = sorted[sorted.length - 1]?.endTime - sorted[0]?.timestamp;
411
+
412
+ // Identify critical path
413
+ const criticalPath = sorted.filter(r =>
414
+ r.type === 'Document' ||
415
+ (r.type === 'Script' && !r.url.includes('async')) ||
416
+ r.type === 'Stylesheet'
417
+ );
418
+
419
+ // Find blocking resources
420
+ const blockingResources = sorted.filter(r =>
421
+ r.renderBlocking ||
422
+ (r.type === 'Script' && !r.async && !r.defer)
423
+ );
424
+
425
+ // Calculate metrics
426
+ return {
427
+ totalRequests: requests.length,
428
+ totalTime,
429
+ totalSize: requests.reduce((sum, r) => sum + (r.encodedDataLength || 0), 0),
430
+ criticalPath,
431
+ blockingResources,
432
+ byType: groupByType(requests),
433
+ recommendations: generateWaterfallRecommendations(requests),
434
+ };
435
+ }
436
+
437
+ // Memory leak detection
438
+ async function detectMemoryLeaks(
439
+ client: CDP.Client,
440
+ actions: () => Promise<void>,
441
+ iterations: number = 3
442
+ ): Promise<MemoryLeakReport> {
443
+ const snapshots: HeapSnapshot[] = [];
444
+
445
+ // Take initial snapshot
446
+ snapshots.push(await takeHeapSnapshot(client));
447
+
448
+ // Perform actions multiple times
449
+ for (let i = 0; i < iterations; i++) {
450
+ await actions();
451
+ await client.HeapProfiler.collectGarbage();
452
+ await new Promise(r => setTimeout(r, 100));
453
+ snapshots.push(await takeHeapSnapshot(client));
454
+ }
455
+
456
+ // Analyze heap growth
457
+ const heapGrowth = analyzeHeapGrowth(snapshots);
458
+ const retainedObjects = findRetainedObjects(snapshots);
459
+
460
+ return {
461
+ hasLeak: heapGrowth.trend === 'increasing',
462
+ heapGrowth,
463
+ retainedObjects,
464
+ recommendations: generateMemoryRecommendations(retainedObjects),
465
+ };
466
+ }
467
+ ```
468
+
469
+ ### 4. Bundle Analysis
470
+
471
+ ```typescript
472
+ import { BundleAnalyzerPlugin } from 'webpack-bundle-analyzer';
473
+ import { visualizer } from 'rollup-plugin-visualizer';
474
+
475
+ interface BundleAnalysis {
476
+ totalSize: number;
477
+ gzipSize: number;
478
+ modules: ModuleInfo[];
479
+ duplicates: DuplicateModule[];
480
+ largestModules: ModuleInfo[];
481
+ recommendations: string[];
482
+ }
483
+
484
+ // Webpack bundle analysis
485
+ function createBundleAnalyzerConfig(): BundleAnalyzerPlugin {
486
+ return new BundleAnalyzerPlugin({
487
+ analyzerMode: 'json',
488
+ reportFilename: 'bundle-report.json',
489
+ generateStatsFile: true,
490
+ statsFilename: 'bundle-stats.json',
491
+ });
492
+ }
493
+
494
+ // Analyze bundle stats
495
+ async function analyzeBundleStats(statsPath: string): Promise<BundleAnalysis> {
496
+ const stats = JSON.parse(await fs.readFile(statsPath, 'utf-8'));
497
+
498
+ const modules = flattenModules(stats.modules);
499
+ const duplicates = findDuplicates(modules);
500
+
501
+ // Calculate sizes
502
+ const totalSize = modules.reduce((sum, m) => sum + m.size, 0);
503
+ const gzipSize = await calculateGzipSize(statsPath);
504
+
505
+ // Sort by size
506
+ const largestModules = [...modules]
507
+ .sort((a, b) => b.size - a.size)
508
+ .slice(0, 20);
509
+
510
+ return {
511
+ totalSize,
512
+ gzipSize,
513
+ modules,
514
+ duplicates,
515
+ largestModules,
516
+ recommendations: generateBundleRecommendations({
517
+ totalSize,
518
+ duplicates,
519
+ largestModules,
520
+ }),
521
+ };
522
+ }
523
+
524
+ // Find duplicate modules
525
+ function findDuplicates(modules: ModuleInfo[]): DuplicateModule[] {
526
+ const modulesByName = new Map<string, ModuleInfo[]>();
527
+
528
+ for (const module of modules) {
529
+ const name = getModuleName(module.identifier);
530
+ const existing = modulesByName.get(name) || [];
531
+ existing.push(module);
532
+ modulesByName.set(name, existing);
533
+ }
534
+
535
+ return Array.from(modulesByName.entries())
536
+ .filter(([_, instances]) => instances.length > 1)
537
+ .map(([name, instances]) => ({
538
+ name,
539
+ instances: instances.length,
540
+ totalSize: instances.reduce((sum, m) => sum + m.size, 0),
541
+ versions: [...new Set(instances.map(m => getModuleVersion(m.identifier)))],
542
+ }))
543
+ .sort((a, b) => b.totalSize - a.totalSize);
544
+ }
545
+
546
+ // Generate bundle recommendations
547
+ function generateBundleRecommendations(analysis: {
548
+ totalSize: number;
549
+ duplicates: DuplicateModule[];
550
+ largestModules: ModuleInfo[];
551
+ }): string[] {
552
+ const recommendations: string[] = [];
553
+
554
+ // Size recommendations
555
+ if (analysis.totalSize > 500 * 1024) {
556
+ recommendations.push(
557
+ 'Consider code splitting to reduce initial bundle size',
558
+ 'Use dynamic imports for routes and large components',
559
+ );
560
+ }
561
+
562
+ // Duplicate recommendations
563
+ if (analysis.duplicates.length > 0) {
564
+ recommendations.push(
565
+ `Found ${analysis.duplicates.length} duplicate packages - dedupe with npm/yarn`,
566
+ 'Consider using webpack.optimize.ModuleConcatenationPlugin',
567
+ );
568
+
569
+ const biggestDupe = analysis.duplicates[0];
570
+ if (biggestDupe) {
571
+ recommendations.push(
572
+ `Largest duplicate: ${biggestDupe.name} (${formatBytes(biggestDupe.totalSize)})`,
573
+ );
574
+ }
575
+ }
576
+
577
+ // Large module recommendations
578
+ const veryLargeModules = analysis.largestModules.filter(m => m.size > 100 * 1024);
579
+ if (veryLargeModules.length > 0) {
580
+ recommendations.push(
581
+ 'Large modules detected - consider lazy loading:',
582
+ ...veryLargeModules.slice(0, 3).map(m =>
583
+ ` - ${m.name}: ${formatBytes(m.size)}`
584
+ ),
585
+ );
586
+ }
587
+
588
+ return recommendations;
589
+ }
590
+ ```
591
+
592
+ ### 5. Performance Budget
593
+
594
+ ```typescript
595
+ interface PerformanceBudget {
596
+ metrics: MetricBudget[];
597
+ resources: ResourceBudget[];
598
+ }
599
+
600
+ interface MetricBudget {
601
+ metric: string;
602
+ budget: number;
603
+ unit: 'ms' | 'score' | 'bytes';
604
+ }
605
+
606
+ interface ResourceBudget {
607
+ type: string;
608
+ budget: number;
609
+ count?: number;
610
+ }
611
+
612
+ // Default performance budget
613
+ const DEFAULT_BUDGET: PerformanceBudget = {
614
+ metrics: [
615
+ { metric: 'LCP', budget: 2500, unit: 'ms' },
616
+ { metric: 'FID', budget: 100, unit: 'ms' },
617
+ { metric: 'CLS', budget: 0.1, unit: 'score' },
618
+ { metric: 'TTI', budget: 3800, unit: 'ms' },
619
+ { metric: 'TBT', budget: 200, unit: 'ms' },
620
+ ],
621
+ resources: [
622
+ { type: 'script', budget: 300 * 1024 },
623
+ { type: 'stylesheet', budget: 50 * 1024 },
624
+ { type: 'image', budget: 500 * 1024 },
625
+ { type: 'font', budget: 100 * 1024 },
626
+ { type: 'total', budget: 1000 * 1024 },
627
+ ],
628
+ };
629
+
630
+ // Check budget violations
631
+ function checkPerformanceBudget(
632
+ metrics: PerformanceMetrics,
633
+ resources: ResourceMetrics,
634
+ budget: PerformanceBudget = DEFAULT_BUDGET
635
+ ): BudgetReport {
636
+ const violations: BudgetViolation[] = [];
637
+
638
+ // Check metric budgets
639
+ for (const { metric, budget: limit, unit } of budget.metrics) {
640
+ const actual = metrics[metric.toLowerCase()];
641
+ if (actual > limit) {
642
+ violations.push({
643
+ type: 'metric',
644
+ name: metric,
645
+ budget: limit,
646
+ actual,
647
+ unit,
648
+ overBy: ((actual - limit) / limit * 100).toFixed(1) + '%',
649
+ });
650
+ }
651
+ }
652
+
653
+ // Check resource budgets
654
+ for (const { type, budget: limit, count } of budget.resources) {
655
+ const resource = resources[type];
656
+ if (resource.size > limit) {
657
+ violations.push({
658
+ type: 'resource',
659
+ name: type,
660
+ budget: limit,
661
+ actual: resource.size,
662
+ unit: 'bytes',
663
+ overBy: formatBytes(resource.size - limit),
664
+ });
665
+ }
666
+ if (count && resource.count > count) {
667
+ violations.push({
668
+ type: 'resource-count',
669
+ name: `${type} count`,
670
+ budget: count,
671
+ actual: resource.count,
672
+ unit: 'requests',
673
+ });
674
+ }
675
+ }
676
+
677
+ return {
678
+ passed: violations.length === 0,
679
+ violations,
680
+ summary: generateBudgetSummary(violations),
681
+ };
682
+ }
683
+
684
+ // Performance regression test
685
+ async function runPerformanceRegression(
686
+ url: string,
687
+ baseline: PerformanceMetrics,
688
+ threshold: number = 0.1 // 10% regression threshold
689
+ ): Promise<RegressionReport> {
690
+ const current = await runLighthouseAudit({ url });
691
+ const regressions: Regression[] = [];
692
+
693
+ for (const [metric, baselineValue] of Object.entries(baseline)) {
694
+ const currentValue = current.metrics[metric];
695
+ const change = (currentValue - baselineValue) / baselineValue;
696
+
697
+ if (change > threshold) {
698
+ regressions.push({
699
+ metric,
700
+ baseline: baselineValue,
701
+ current: currentValue,
702
+ change: `+${(change * 100).toFixed(1)}%`,
703
+ severity: change > 0.25 ? 'critical' : 'warning',
704
+ });
705
+ }
706
+ }
707
+
708
+ return {
709
+ passed: regressions.length === 0,
710
+ regressions,
711
+ metrics: current.metrics,
712
+ comparison: generateComparison(baseline, current.metrics),
713
+ };
714
+ }
715
+ ```
716
+
717
+ ### 6. Automated Performance CI/CD
718
+
719
+ ```yaml
720
+ # .github/workflows/performance.yml
721
+ name: Performance Audit
722
+
723
+ on:
724
+ pull_request:
725
+ branches: [main]
726
+ push:
727
+ branches: [main]
728
+
729
+ jobs:
730
+ lighthouse:
731
+ runs-on: ubuntu-latest
732
+ steps:
733
+ - uses: actions/checkout@v4
734
+
735
+ - name: Setup Node.js
736
+ uses: actions/setup-node@v4
737
+ with:
738
+ node-version: '20'
739
+
740
+ - name: Install dependencies
741
+ run: npm ci
742
+
743
+ - name: Build
744
+ run: npm run build
745
+
746
+ - name: Start server
747
+ run: npm run start &
748
+
749
+ - name: Run Lighthouse
750
+ uses: treosh/lighthouse-ci-action@v10
751
+ with:
752
+ urls: |
753
+ http://localhost:3000
754
+ http://localhost:3000/products
755
+ budgetPath: ./performance-budget.json
756
+ uploadArtifacts: true
757
+
758
+ - name: Check performance budget
759
+ run: |
760
+ node scripts/check-performance-budget.js \
761
+ --budget ./performance-budget.json \
762
+ --results .lighthouseci/*.json
763
+ ```
764
+
765
+ ## Use Cases
766
+
767
+ ### 1. E-commerce Performance Optimization
768
+
769
+ ```typescript
770
+ // E-commerce specific performance audit
771
+ async function auditEcommerceSite(baseUrl: string): Promise<EcommerceAudit> {
772
+ const pages = [
773
+ { name: 'Home', path: '/' },
774
+ { name: 'Category', path: '/products' },
775
+ { name: 'Product', path: '/products/1' },
776
+ { name: 'Cart', path: '/cart' },
777
+ { name: 'Checkout', path: '/checkout' },
778
+ ];
779
+
780
+ const results = await Promise.all(
781
+ pages.map(async page => ({
782
+ ...page,
783
+ audit: await runLighthouseAudit({
784
+ url: `${baseUrl}${page.path}`,
785
+ device: 'mobile',
786
+ }),
787
+ }))
788
+ );
789
+
790
+ return {
791
+ pages: results,
792
+ criticalPath: identifyCriticalPath(results),
793
+ conversionImpact: estimateConversionImpact(results),
794
+ recommendations: prioritizeRecommendations(results),
795
+ };
796
+ }
797
+ ```
798
+
799
+ ### 2. SPA Performance Monitoring
800
+
801
+ ```typescript
802
+ // Single Page App performance monitoring
803
+ function initSPAPerformanceMonitoring(): void {
804
+ // Track route changes
805
+ let routeStartTime: number;
806
+
807
+ router.beforeEach(() => {
808
+ routeStartTime = performance.now();
809
+ });
810
+
811
+ router.afterEach((to) => {
812
+ const routeTime = performance.now() - routeStartTime;
813
+
814
+ // Track custom metric
815
+ performance.measure(`route-${to.name}`, {
816
+ start: routeStartTime,
817
+ duration: routeTime,
818
+ });
819
+
820
+ // Report to analytics
821
+ analytics.track('route_performance', {
822
+ route: to.name,
823
+ duration: routeTime,
824
+ timestamp: Date.now(),
825
+ });
826
+ });
827
+
828
+ // Monitor long tasks
829
+ const observer = new PerformanceObserver((list) => {
830
+ for (const entry of list.getEntries()) {
831
+ if (entry.duration > 50) {
832
+ console.warn('Long task detected:', entry.duration, 'ms');
833
+ analytics.track('long_task', {
834
+ duration: entry.duration,
835
+ startTime: entry.startTime,
836
+ });
837
+ }
838
+ }
839
+ });
840
+
841
+ observer.observe({ entryTypes: ['longtask'] });
842
+ }
843
+ ```
844
+
845
+ ## Best Practices
846
+
847
+ ### Do's
848
+
849
+ - **Test in production-like conditions** - Use throttling and real device testing
850
+ - **Monitor continuously** - Set up RUM for ongoing performance tracking
851
+ - **Focus on user-centric metrics** - Prioritize Core Web Vitals
852
+ - **Automate testing** - Include performance tests in CI/CD
853
+ - **Set budgets** - Define and enforce performance budgets
854
+ - **Profile incrementally** - Test before and after changes
855
+
856
+ ### Don'ts
857
+
858
+ - Don't test only on fast connections
859
+ - Don't ignore mobile performance
860
+ - Don't optimize prematurely without data
861
+ - Don't rely solely on synthetic testing
862
+ - Don't forget about third-party scripts
863
+ - Don't ignore cumulative layout shift
864
+
865
+ ### Performance Checklist
866
+
867
+ ```markdown
868
+ ## Pre-Launch Performance Checklist
869
+
870
+ ### Core Web Vitals
871
+ - [ ] LCP < 2.5s on mobile
872
+ - [ ] FID < 100ms
873
+ - [ ] CLS < 0.1
874
+ - [ ] INP < 200ms
875
+
876
+ ### Resource Optimization
877
+ - [ ] Images optimized (WebP/AVIF, lazy loaded)
878
+ - [ ] JavaScript bundled and minified
879
+ - [ ] CSS optimized and critical CSS inlined
880
+ - [ ] Fonts optimized (preload, font-display)
881
+
882
+ ### Caching
883
+ - [ ] Proper cache headers set
884
+ - [ ] Service worker for offline support
885
+ - [ ] CDN configured
886
+
887
+ ### Monitoring
888
+ - [ ] RUM implemented
889
+ - [ ] Performance budget defined
890
+ - [ ] CI/CD performance tests
891
+ ```
892
+
893
+ ## Related Skills
894
+
895
+ - **frontend-design** - UI performance considerations
896
+ - **devops** - Infrastructure optimization
897
+ - **docker** - Container performance
898
+ - **kubernetes** - Scaling for performance
899
+
900
+ ## Reference Resources
901
+
902
+ - [Web Vitals](https://web.dev/vitals/)
903
+ - [Lighthouse Documentation](https://developer.chrome.com/docs/lighthouse/)
904
+ - [Chrome DevTools Performance](https://developer.chrome.com/docs/devtools/performance/)
905
+ - [web.dev Performance](https://web.dev/learn/performance/)