#ai /

AI-Assisted Frontend Performance Optimization: From Monitoring to Auto-Fix

Exploring how to use AI to assist frontend performance optimization, covering performance monitoring, bottleneck identification, auto-fix, and continuous optimization

Goal

Frontend performance optimization has always been an important task for developers, but traditional approaches rely on human experience and manual analysis. AI is changing this -- it can automatically identify performance bottlenecks, generate optimization plans, and even auto-fix issues. This article explores how to use AI to assist frontend performance optimization.

Background

Traditional Performance Optimization Pain Points

| Pain Point | Description | |------------|-------------| | Experience-Dependent | Requires senior engineers to identify issues | | Time-Consuming Analysis | Manual analysis of performance data is very time-consuming | | Scattered Optimization | Hard to systematically manage various optimization points | | Hard to Measure | Difficult to quantify optimization effectiveness |

AI Optimization Advantages

  • Auto-Identification: AI can automatically discover performance bottlenecks
  • Intelligent Analysis: Deep analysis of root causes
  • Plan Generation: Automatically generate optimization plans
  • Continuous Monitoring: Real-time performance change monitoring

Performance Monitoring System

Core Metrics Collection

interface PerformanceMetrics {
lcp: number; inp: number; cls: number; fcp: number; ttfb: number;
jsSize: number; cssSize: number; imageSize: number;
totalResources: number; longTasks: number; memoryUsage: number;
}
class PerformanceMonitor {
private metrics: PerformanceMetrics;
private observer: PerformanceObserver;
constructor() {
this.metrics = this.initMetrics();
this.observer = this.initObserver();
}
private initMetrics(): PerformanceMetrics {
return { lcp: 0, inp: 0, cls: 0, fcp: 0, ttfb: 0, jsSize: 0, cssSize: 0, imageSize: 0, totalResources: 0, longTasks: 0, memoryUsage: 0 };
}
private initObserver(): PerformanceObserver {
const observer = new PerformanceObserver((list) => {
for (const entry of list.getEntries()) this.processEntry(entry);
});
observer.observe({ type: 'largest-contentful-paint', buffered: true });
observer.observe({ type: 'first-input', buffered: true });
observer.observe({ type: 'layout-shift', buffered: true });
observer.observe({ type: 'paint', buffered: true });
observer.observe({ type: 'resource', buffered: true });
observer.observe({ type: 'longtask', buffered: true });
return observer;
}
private processEntry(entry: PerformanceEntry): void {
switch (entry.entryType) {
case 'largest-contentful-paint': this.metrics.lcp = entry.startTime; break;
case 'first-input': this.metrics.inp = (entry as any).processingStart - entry.startTime; break;
case 'layout-shift': if (!(entry as any).hadRecentInput) this.metrics.cls += (entry as any).value; break;
case 'paint': if (entry.name === 'first-contentful-paint') this.metrics.fcp = entry.startTime; break;
case 'resource': this.processResource(entry as PerformanceResourceTiming); break;
case 'longtask': this.metrics.longTasks++; break;
}
}
private processResource(entry: PerformanceResourceTiming): void {
const size = entry.transferSize || 0;
if (entry.initiatorType === 'script') this.metrics.jsSize += size;
else if (entry.initiatorType === 'css' || entry.initiatorType === 'link') this.metrics.cssSize += size;
else if (entry.initiatorType === 'img') this.metrics.imageSize += size;
this.metrics.totalResources++;
}
getMetrics(): PerformanceMetrics { return { ...this.metrics }; }
async report(): Promise<void> {
const metrics = this.getMetrics();
await fetch('/api/performance/report', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ url: window.location.href, metrics, userAgent: navigator.userAgent, timestamp: Date.now() }),
});
}
}

AI Analysis Engine

Performance Bottleneck Identification

import { ChatOpenAI } from '@langchain/openai';
interface PerformanceIssue {
id: string;
type: 'critical' | 'warning' | 'info';
category: 'loading' | 'rendering' | 'interaction' | 'memory';
title: string;
description: string;
impact: string;
recommendation: string;
code?: string;
}
class AIPerformanceAnalyzer {
private llm: ChatOpenAI;
constructor() { this.llm = new ChatOpenAI({ modelName: 'gpt-4o' }); }
async analyze(metrics: PerformanceMetrics, pageData: any): Promise<PerformanceIssue[]> {
const prompt = `Analyze the following frontend performance data and identify bottlenecks and optimization opportunities.
Performance metrics:
- LCP: ${metrics.lcp}ms (target: <2500ms)
- INP: ${metrics.inp}ms (target: <200ms)
- CLS: ${metrics.cls} (target: <0.1)
- FCP: ${metrics.fcp}ms (target: <1800ms)
- TTFB: ${metrics.ttfb}ms (target: <800ms)
Resource sizes:
- JavaScript: ${(metrics.jsSize / 1024).toFixed(2)} KB
- CSS: ${(metrics.cssSize / 1024).toFixed(2)} KB
- Images: ${(metrics.imageSize / 1024).toFixed(2)} KB
- Total resources: ${metrics.totalResources}
Other:
- Long tasks: ${metrics.longTasks}
- Memory usage: ${(metrics.memoryUsage / 1024 / 1024).toFixed(2)} MB
Page data: ${JSON.stringify(pageData, null, 2)}
Identify:
1. Loading performance issues
2. Rendering performance issues
3. Interaction performance issues
4. Memory issues
5. Resource optimization opportunities
Output JSON:
{
"issues": [{ "type": "critical|warning|info", "category": "loading|rendering|interaction|memory", "title": "issue title", "description": "issue description", "impact": "impact description", "recommendation": "optimization suggestion" }]
}`;
const response = await this.llm.invoke(prompt);
const result = JSON.parse(response.content as string);
return result.issues.map((issue: any, index: number) => ({ id: `issue-${Date.now()}-${index}`, ...issue }));
}
async generateOptimizationCode(issue: PerformanceIssue): Promise<string> {
const prompt = `Generate optimization code for the following performance issue:
Issue: ${issue.title}
Description: ${issue.description}
Recommendation: ${issue.recommendation}
Generate specific optimization code including:
1. Fix code
2. Configuration adjustments
3. Best practice examples`;
const response = await this.llm.invoke(prompt);
return response.content as string;
}
}

Auto-Fix System

interface FixResult {
issueId: string;
status: 'applied' | 'failed' | 'skipped';
changes: CodeChange[];
explanation: string;
}
interface CodeChange {
file: string;
before: string;
after: string;
description: string;
}
class AIAutoFixer {
private analyzer: AIPerformanceAnalyzer;
private llm: ChatOpenAI;
constructor() {
this.analyzer = new AIPerformanceAnalyzer();
this.llm = new ChatOpenAI({ modelName: 'gpt-4o' });
}
async analyzeAndFix(metrics: PerformanceMetrics, sourceCode: Map<string, string>): Promise<FixResult[]> {
const issues = await this.analyzer.analyze(metrics, { sourceFiles: Array.from(sourceCode.keys()) });
const results: FixResult[] = [];
for (const issue of issues) {
if (issue.type === 'critical' || issue.type === 'warning') {
const result = await this.fixIssue(issue, sourceCode);
results.push(result);
}
}
return results;
}
private async fixIssue(issue: PerformanceIssue, sourceCode: Map<string, string>): Promise<FixResult> {
const relevantFiles = this.findRelevantFiles(issue, sourceCode);
const prompt = `Fix the following performance issue:
Issue: ${issue.title}
Description: ${issue.description}
Related source code:
${Array.from(relevantFiles.entries()).map(([file, code]) => `--- ${file} ---\n${code}`).join('\n\n')}
Generate a fix including:
1. Specific code changes
2. Change explanation
3. Expected effect
Output JSON:
{
"changes": [{ "file": "file path", "before": "code before", "after": "code after", "description": "change description" }],
"explanation": "overall explanation"
}`;
const response = await this.llm.invoke(prompt);
const result = JSON.parse(response.content as string);
return { issueId: issue.id, status: 'applied', changes: result.changes, explanation: result.explanation };
}
private findRelevantFiles(issue: PerformanceIssue, sourceCode: Map<string, string>): Map<string, string> {
const relevant = new Map<string, string>();
const keywords = issue.description.toLowerCase().split(' ');
sourceCode.forEach((code, file) => {
const lowerCode = code.toLowerCase();
if (keywords.some(kw => lowerCode.includes(kw))) relevant.set(file, code);
});
return relevant;
}
}

Practical Cases

Case 1: Image Optimization

const imageIssue = {
type: 'warning', category: 'loading',
title: 'Images not using modern formats',
description: 'Page uses 15 JPEG/PNG images that could be converted to WebP/AVIF format to reduce file size',
impact: 'Estimated 30-50% reduction in image size',
recommendation: 'Use <picture> tag to provide WebP/AVIF format images',
};
const optimizedCode = `
// Before
<img src="/images/hero.jpg" alt="Hero" />
// After
<picture>
<source srcset="/images/hero.avif" type="image/avif" />
<source srcset="/images/hero.webp" type="image/webp" />
<img src="/images/hero.jpg" alt="Hero" loading="lazy" />
</picture>
`;

Case 2: Code Splitting

const codeSplitIssue = {
type: 'critical', category: 'loading',
title: 'JavaScript bundle too large',
description: 'Main bundle is 850KB, exceeding the recommended 200KB limit',
impact: 'First paint time increases by 2-3 seconds',
recommendation: 'Implement code splitting with route and component lazy loading',
};
const codeSplitCode = `
// Before
import HeavyComponent from './HeavyComponent';
// After
const HeavyComponent = lazy(() => import('./HeavyComponent'));
function App() {
return (
<Suspense fallback={<Loading />}>
<HeavyComponent />
</Suspense>
);
}
`;

Case 3: Memory Leak

const memoryIssue = {
type: 'critical', category: 'memory',
title: 'Potential memory leak detected',
description: 'Event listeners not properly cleaned up, may cause memory leaks',
impact: 'Page performance degrades over extended use',
recommendation: 'Clean up event listeners on component unmount',
};
const memoryFix = `
// Before
useEffect(() => {
window.addEventListener('scroll', handleScroll);
}, []);
// After
useEffect(() => {
const handleScroll = () => { /* handle scroll */ };
window.addEventListener('scroll', handleScroll);
return () => { window.removeEventListener('scroll', handleScroll); };
}, []);
`;

Continuous Optimization

Performance Budget

interface PerformanceBudget {
lcp: number; inp: number; cls: number; fcp: number; ttfb: number;
jsSize: number; cssSize: number; imageSize: number;
}
const defaultBudget: PerformanceBudget = {
lcp: 2500, inp: 200, cls: 0.1, fcp: 1800, ttfb: 800,
jsSize: 200 * 1024, cssSize: 50 * 1024, imageSize: 500 * 1024,
};
class PerformanceBudgetChecker {
private budget: PerformanceBudget;
constructor(budget: PerformanceBudget = defaultBudget) { this.budget = budget; }
check(metrics: PerformanceMetrics): BudgetReport {
const violations: BudgetViolation[] = [];
if (metrics.lcp > this.budget.lcp) violations.push({ metric: 'LCP', actual: metrics.lcp, budget: this.budget.lcp, overage: ((metrics.lcp - this.budget.lcp) / this.budget.lcp) * 100 });
if (metrics.inp > this.budget.inp) violations.push({ metric: 'INP', actual: metrics.inp, budget: this.budget.inp, overage: ((metrics.inp - this.budget.inp) / this.budget.inp) * 100 });
return { passed: violations.length === 0, violations, score: this.calculateScore(violations) };
}
private calculateScore(violations: BudgetViolation[]): number {
if (violations.length === 0) return 100;
const totalOverage = violations.reduce((sum, v) => sum + v.overage, 0);
return Math.max(0, 100 - totalOverage);
}
}
interface BudgetViolation { metric: string; actual: number; budget: number; overage: number; }
interface BudgetReport { passed: boolean; violations: BudgetViolation[]; score: number; }

Summary

Core value of AI-assisted frontend performance optimization:

  1. Auto-Identification: AI automatically discovers performance bottlenecks.
  2. Intelligent Analysis: Deep analysis of root causes.
  3. Plan Generation: Automatically generate optimization code.
  4. Continuous Monitoring: Real-time performance change monitoring.
  5. Budget Management: Automatic performance budget checking.

AI performance optimization best practices:

  • Establish a comprehensive performance monitoring system
  • Use AI for assisted analysis, but make human decisions
  • Establish performance budgets for continuous tracking
  • Quantify optimization effectiveness

AI will not completely replace manual performance optimization, but it will greatly improve efficiency. The future trend is AI handling repetitive optimization tasks while humans focus on architecture-level performance design.

Like this post? Tweet to share it with others or open an issue to discuss with me!