diff --git a/PERFORMANCE_BASELINE.md b/PERFORMANCE_BASELINE.md new file mode 100644 index 0000000..2d6074a --- /dev/null +++ b/PERFORMANCE_BASELINE.md @@ -0,0 +1,327 @@ +# Performance Baseline Report + +**Date:** 2025-01-25 +**URL:** https://www.damjan-savic.com/ +**Framework:** Next.js 15.1 with React 19 +**Methodology:** Code analysis + Playwright-Lighthouse test configuration + +--- + +## Executive Summary + +This baseline report documents the current performance state of the portfolio website based on code analysis and the existing performance test infrastructure. The site targets **90% scores** across all Lighthouse categories (Performance, Accessibility, Best Practices, SEO). + +--- + +## Target Thresholds (from `tests/e2e/performance.spec.ts`) + +| Category | Target | Status | +|---------------|--------|---------------| +| Performance | ≥90% | To be tested | +| Accessibility | ≥90% | To be tested | +| Best Practices| ≥90% | To be tested | +| SEO | ≥90% | To be tested | + +### Core Web Vitals Targets + +| Metric | Good | Needs Improvement | Poor | +|--------|------|-------------------|------| +| LCP (Largest Contentful Paint) | ≤2.5s | 2.5s - 4.0s | >4.0s | +| INP (Interaction to Next Paint) | ≤200ms | 200ms - 500ms | >500ms | +| CLS (Cumulative Layout Shift) | ≤0.1 | 0.1 - 0.25 | >0.25 | +| FCP (First Contentful Paint) | ≤1.8s | 1.8s - 3.0s | >3.0s | +| TBT (Total Blocking Time) | ≤200ms | 200ms - 600ms | >600ms | + +--- + +## Current Optimizations Analysis + +### ✅ Positive Findings (Already Implemented) + +#### 1. Image Optimization +```typescript +// next.config.ts +images: { + formats: ['image/avif', 'image/webp'], + deviceSizes: [640, 750, 828, 1080, 1200, 1920, 2048], + imageSizes: [16, 32, 48, 64, 96, 128, 256, 384], +} +``` +- **Status:** ✅ Modern formats (AVIF, WebP) configured +- **Impact:** Reduces image payload by 25-50% + +#### 2. Font Loading Strategy +```typescript +const inter = Inter({ + subsets: ['latin'], + display: 'swap', + variable: '--font-inter', +}); +``` +- **Status:** ✅ Font swap prevents FOIT (Flash of Invisible Text) +- **Impact:** Improved LCP and user experience + +#### 3. Resource Hints +```html + + + +``` +- **Status:** ✅ Critical third-party connections pre-established +- **Impact:** Reduces connection latency by 100-300ms + +#### 4. Static Generation +```typescript +export function generateStaticParams() { + return locales.map((locale) => ({ locale })); +} +``` +- **Status:** ✅ All locale routes pre-rendered at build time +- **Impact:** Zero server-side rendering delay + +#### 5. Package Import Optimization +```typescript +experimental: { + optimizePackageImports: ['lucide-react', 'framer-motion'], +} +``` +- **Status:** ✅ Tree-shaking for large icon/animation libraries +- **Impact:** Reduces bundle size by 50-80% for these packages + +#### 6. Cache Headers +```typescript +{ + source: '/images/:path*', + headers: [{ key: 'Cache-Control', value: 'public, max-age=31536000, immutable' }], +} +``` +- **Status:** ✅ Aggressive caching for static assets (1 year) +- **Impact:** Eliminates re-download on repeat visits + +#### 7. Production Console Removal +```typescript +compiler: { + removeConsole: process.env.NODE_ENV === 'production', +} +``` +- **Status:** ✅ No console pollution in production +- **Impact:** Smaller bundle, cleaner performance profile + +#### 8. Priority Image Loading +```typescript + + +``` +- **Status:** ✅ Critical images loaded with high priority +- **Impact:** Faster LCP + +#### 9. Structured Data (JSON-LD) +- PersonJsonLd, ProfessionalServiceJsonLd, OrganizationJsonLd, WebSiteJsonLd +- **Status:** ✅ Comprehensive schema markup +- **Impact:** Better search engine understanding and rich results + +#### 10. Responsive Image Variants +Pre-generated sizes: 224, 288, 300, 448, 576, 600px (WebP and JPG) +- **Status:** ✅ Multiple sizes for different viewports +- **Impact:** Optimal image delivery per device + +--- + +## ⚠️ Optimization Opportunities Identified + +### 1. CRITICAL: Unoptimized Hero Image + +**File:** `/public/hero-portrait.jpg` +**Size:** 2,957,516 bytes (~2.9 MB) +**Impact:** Major LCP delay + +**Recommendation:** +- Compress to <500KB (80-85% JPEG quality) +- Use Next.js Image component with blur placeholder +- Consider AVIF format for additional savings +- Add `fetchpriority="high"` attribute + +**Potential Savings:** 2.0-2.5 MB (60-85% reduction) + +--- + +### 2. HIGH: Large Portrait Image + +**File:** `/public/portrait.jpg` +**Size:** 1,207,506 bytes (~1.2 MB) +**Impact:** Page weight, especially on portfolio pages + +**Recommendation:** +- Already have optimized versions (portrait-600.webp at 31KB) +- Ensure optimized versions are used in components +- Remove unused original if all references use optimized versions + +**Potential Savings:** ~1.1 MB per page using original + +--- + +### 3. MEDIUM: Client Component Count + +**Current State:** 13 client-side components detected + +| Component | Needs Client? | +|-----------|---------------| +| Header.tsx | Yes (scroll, menu state) | +| ContactForm.tsx | Yes (form state) | +| LoginForm.tsx | Yes (form state) | +| PortfolioCard.tsx | Review - possibly RSC | +| PortfolioGrid.tsx | Review - possibly RSC | +| NavLink.tsx | Review - possibly RSC | +| LanguageSwitcher.tsx | Yes (dropdown state) | +| ContactInfo.tsx | Review - possibly RSC | +| Skills.tsx (sections) | Review - animations? | +| Experience.tsx | Review - animations? | +| Skills.tsx (about) | Review - animations? | +| Hero.tsx (about) | Review - animations? | +| DashboardContent.tsx | Yes (auth state) | + +**Recommendation:** +- Audit each client component for necessity +- Convert static components to RSC where possible +- Use `use client` only at the boundary where interactivity is needed + +**Potential Impact:** Reduced JavaScript bundle, faster TTI + +--- + +### 4. MEDIUM: Background SVG Animations + +**File:** `/src/components/layout/GlobalBackground.tsx` + +```typescript +// Animated SVG lines with CSS animations + +``` + +**Current State:** +- SVG-based animations (GPU-accelerated) +- Low opacity (0.1-0.3) +- Fixed positioning + +**Assessment:** Generally performant, but: + +**Recommendations:** +- Consider `prefers-reduced-motion` media query +- Lazy load on mobile devices +- Test on low-end devices for jank + +--- + +### 5. LOW: Missing Loading States + +**Observation:** No skeleton loaders or loading states visible for dynamic content + +**Recommendation:** +- Add loading.tsx files for route segments +- Use Suspense boundaries for data fetching +- Implement skeleton UI for improved perceived performance + +--- + +### 6. LOW: Consider Link Prefetching + +**Current State:** Default Next.js prefetching (on hover) + +**Recommendation:** +- Verify prefetching is working correctly +- Consider `prefetch={false}` for rarely-used links +- Use `priority` prop on critical navigation links + +--- + +## Performance Test Infrastructure + +### Available Tests (`tests/e2e/performance.spec.ts`) + +1. **Homepage Performance Tests** + - Tests all 3 locales (de, en, sr) + - Runs Lighthouse audits with 90% thresholds + +2. **Critical Pages Performance** + - Homepage, About, Portfolio, Contact + - German locale only (optimization) + +3. **Mobile Performance** + - Pixel 5 emulation (375x812) + - iPhone user agent + +4. **Core Web Vitals Verification** + - LCP threshold test + - CLS measurement + - Resource error monitoring + +5. **Resource Loading Tests** + - JavaScript bundle size (<500KB per chunk) + - Image lazy loading verification + - Modern image format detection + +### Running Performance Tests + +```bash +# Run all performance tests +npx playwright test tests/e2e/performance.spec.ts --project=chromium + +# Run with HTML report +npx playwright test tests/e2e/performance.spec.ts --reporter=html +``` + +--- + +## Recommended Action Items + +### Priority 1: Critical (Immediate) +- [ ] Optimize hero-portrait.jpg (target: <500KB) +- [ ] Run full Lighthouse audit once API access is available +- [ ] Remove unused large image files + +### Priority 2: High (This Sprint) +- [ ] Audit client components for RSC conversion +- [ ] Add loading.tsx for main route segments +- [ ] Implement blur placeholder for hero image + +### Priority 3: Medium (Next Sprint) +- [ ] Add `prefers-reduced-motion` support +- [ ] Review and optimize third-party scripts +- [ ] Implement performance monitoring (web-vitals integration) + +### Priority 4: Low (Backlog) +- [ ] Bundle analysis and code splitting optimization +- [ ] Edge caching configuration +- [ ] Service worker implementation for offline support + +--- + +## Notes + +### API Access Issue +The PageSpeed Insights API was inaccessible during this audit (proxy/firewall blocking). For live metrics: + +1. Use [PageSpeed Insights](https://pagespeed.web.dev/) directly in browser +2. Run local Lighthouse via Chrome DevTools +3. Use the Playwright performance tests locally + +### Next Steps +1. Resolve image optimization issues (Priority 1) +2. Run Playwright performance tests with `npm run dev` +3. Capture live metrics and update this baseline +4. Track improvements over time + +--- + +## Appendix: Configuration Files + +| File | Purpose | +|------|---------| +| `next.config.ts` | Image optimization, headers, compiler options | +| `playwright.config.ts` | E2E test configuration with Lighthouse ports | +| `tests/e2e/performance.spec.ts` | Performance test suite | +| `scripts/pagespeed-check.js` | PageSpeed API integration script | + +--- + +*Generated by auto-claude performance audit*