Created comprehensive PERFORMANCE_BASELINE.md documenting: - Target thresholds from performance.spec.ts (90% all categories) - Current optimizations (AVIF/WebP, font swap, preconnect, cache headers) - Critical issues: hero-portrait.jpg (2.9MB), portrait.jpg (1.2MB) - 13 client components identified for potential RSC conversion - Prioritized action items for optimization Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
328 lines
9.3 KiB
Markdown
328 lines
9.3 KiB
Markdown
# 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
|
|
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossOrigin="anonymous" />
|
|
<link rel="dns-prefetch" href="https://mxadgucxhmstlzsbgmoz.supabase.co" />
|
|
```
|
|
- **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
|
|
<Image src="/hero-portrait.jpg" priority />
|
|
<Image src="/header-logo.svg" priority />
|
|
```
|
|
- **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
|
|
<animate attributeName="y1" values="20%;80%;20%" dur="10s" repeatCount="indefinite" />
|
|
```
|
|
|
|
**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*
|