8.6 KiB
8.6 KiB
Performance Optimization Guide - CiMa Frontend
Overview
This document outlines the comprehensive performance optimizations implemented to improve Google Core Web Vitals and overall user experience.
✅ Implemented Optimizations
1. Skeleton Loading with Wave Animation
File: src/components/Skeleton.tsx
Features:
Skeletoncomponent: Basic skeleton placeholder with pulse animationSkeletonWavecomponent: Enhanced skeleton with smooth wave animationSkeletonContainercomponent: Wrapper for conditional skeleton/content rendering
Benefits:
- Reduces perceived loading time
- Provides visual feedback during content loading
- Smoother user experience on slower connections
- Wave animation focuses user attention naturally
Usage Example:
import { SkeletonWave } from "@/components/Skeleton";
<SkeletonWave height="300px" />
2. Intersection Observer Hook for Lazy Loading
File: src/components/hooks/useIntersectionObserver.ts
Key Features:
useIntersectionObserver: Tracks visibility of elements as user scrollsuseLazyLoad: Combines intersection observer with loading state management- Configurable threshold and rootMargin
triggerOnceoption to stop observing after first visibility
Benefits:
- Only loads content when user is about to see it
- Reduces initial page load size
- Improves time to interactive (TTI)
- Better battery life on mobile devices
Usage Example:
const [ref, isVisible] = useIntersectionObserver({
threshold: 0.1,
rootMargin: "50px",
triggerOnce: true
});
return (
<div ref={ref}>
{isVisible ? <Content /> : <Skeleton />}
</div>
);
3. LazySection Component
File: src/components/LazySection.tsx
Purpose:
Wrapper component that automatically lazy-loads entire sections of content.
Benefits:
- Semantic and easy to implement
- Automatic skeleton fallback
- Customizable loading placeholder
Usage Example:
<LazySection
className="lazy-section"
skeletonHeight="300px"
skeletonCount={3}
>
<YourHeavyContent />
</LazySection>
4. Optimized Images with OptimizedImage Component
File: src/components/OptimizedImage.tsx
Features:
- Lazy loading for images below the fold
- Skeleton placeholder while loading
- Smooth fade-in transition
loading="lazy"attribute for native browser support- WebP/AVIF format support via Next.js Image
Benefits:
- Reduces Largest Contentful Paint (LCP)
- Prevents Cumulative Layout Shift (CLS)
- Faster initial page load
Usage Example:
import { OptimizedImage } from "@/components/OptimizedImage";
<OptimizedImage
src="/images/architecture.jpg"
alt="Architecture"
width={800}
height={600}
lazy={true}
/>
5. CSS Performance Optimizations
File: src/app/globals.css
Implemented:
/* Async image decoding */
img {
decoding: async;
}
/* Wave animation keyframes */
@keyframes wave { /* Smooth gradient wave effect */ }
/* Prevents CLS for lazy images */
img {
aspect-ratio: auto;
}
/* Content visibility optimization */
.lazy-section {
content-visibility: auto;
contain-intrinsic-size: 0 500px;
}
/* Reduced motion accessibility */
@media (prefers-reduced-motion: reduce) {
/* Disables animations for users who prefer reduced motion */
}
Benefits:
- Faster image rendering with async decoding
- Prevents layout shifts during image load
- Respects user accessibility preferences
- Improves rendering performance
6. Next.js Configuration Optimizations
File: next.config.ts
Features:
- Image format optimization (WebP, AVIF)
- Responsive image sizes
- 1-year cache for images (immutable)
- Package import optimization
- Image compression
Benefits:
- Automatic format selection based on browser
- Smaller images (WebP ~20-30% smaller)
- Better caching strategy
- Faster bundle size
7. Font Optimization
File: src/app/layout.tsx
Implemented:
- Preconnect to Google Fonts servers
- DNS prefetch for faster resolution
- Font display swap (shows fallback immediately)
- Preload strategy for critical fonts
Benefits:
- Reduces font loading latency
- Prevents text cutoff/reflow
- Better perceived performance
- FOUT/FOIT optimization
8. Dynamic Code Splitting
File: src/app/page.tsx
Components:
ServicesSection: Dynamically imported, loads on scrollAboutSection: Dynamically imported, loads on scroll
Benefits:
- Reduces initial JavaScript bundle
- Faster first paint
- Faster time to interactive
- Progressive enhancement
Code:
const ServicesSection = dynamic(
() => import("@/components/sections/ServicesSection"),
{
loading: () => <SkeletonLoader />,
ssr: false
}
);
9. Page-Specific Lazy Sections
Homepage (/src/app/page.tsx):
-
Above Fold (Immediate):
- Hero section (includes CTA)
- Approach section
-
Below Fold (Lazy Loaded):
- Problem/Value comparison
- Services grid (with dynamic import)
- Chi Siamo section (with dynamic import)
- Philosophy section
- CTA section
Contact Page (/src/app/contatti/page.tsx):
-
Above Fold (Immediate):
- Hero section with title
-
Below Fold (Lazy Loaded):
- Contact information
- Team member profiles
📊 Performance Metrics
Expected Improvements:
| Metric | Impact | How Achieved |
|---|---|---|
| LCP (Largest Contentful Paint) | ⬇️-30% | Lazy loading, image optimization, fonts |
| FID (First Input Delay) | ⬇️-40% | Code splitting, reduced JS |
| CLS (Cumulative Layout Shift) | ⬇️-50% | Image aspect ratios, skeletons |
| FCP (First Contentful Paint) | ⬇️-25% | Reduced bundle, lazy loading |
| TTFB (Time to First Byte) | ⬇️-15% | Better resource prioritization |
🎯 Best Practices Implemented
For Google SEO:
- ✅ Semantic HTML structure maintained
- ✅ Metadata properly configured
- ✅ Mobile-first responsive design
- ✅ Core Web Vitals optimized
- ✅ Structured data ready
For User Experience:
- ✅ Perceivable loading states (skeletons)
- ✅ Progressive content revelation
- ✅ Smooth animations
- ✅ Accessibility respected (prefers-reduced-motion)
- ✅ Visual hierarchy maintained
🔧 How to Use
1. Wrapping New Sections
import { LazySection } from "@/components/LazySection";
<LazySection className="lazy-section" skeletonHeight="300px">
<YourContent />
</LazySection>
2. Using Custom Skeleton
<LazySection
skeleton={<CustomSkeleton />}
skeletonHeight="250px"
>
<YourContent />
</LazySection>
3. Optimizing Images
import { OptimizedImage } from "@/components/OptimizedImage";
<OptimizedImage
src="/images/example.jpg"
alt="Description"
width={800}
height={600}
priority={false}
lazy={true}
/>
4. Manual Intersection Observer
const [ref, isVisible] = useIntersectionObserver({
threshold: 0.2,
rootMargin: "100px"
});
🚀 Next Steps for Further Optimization
Priority 1 (High Impact):
- Implement service worker for offline support
- Add image compression/optimization pipeline
- Enable HTTP/2 Server Push for critical resources
- Implement critical CSS extraction
Priority 2 (Medium Impact):
- Add performance monitoring with Web Vitals library
- Implement adaptive loading based on network
- Add resource hints (preload, prefetch)
- Optimize third-party scripts
Priority 3 (Low Impact):
- Implement analytics lazy loading
- Add A/B testing infrastructure
- Create performance budget alerts
- Document lighthouse scores
📈 Monitoring Performance
Tools to Use:
- Google Lighthouse: In Chrome DevTools
- Google PageSpeed Insights: https://pagespeed.web.dev/
- WebPageTest: https://www.webpagetest.org/
- GTmetrix: https://gtmetrix.com/
Check Core Web Vitals:
- Google Search Console (once indexed)
- Chrome UX Report API
- Web Vitals library implementation
📝 Notes
- All lazy-loaded sections include fallback skeletons
- Wave animation is disabled on
prefers-reduced-motion - Images use
decoding="async"for non-blocking rendering - Components maintain SSR compatibility
- Intersection observer threshold set to 0.1 (10% visible)
- Root margin: 50px (starts loading 50px before entering viewport)
Last Updated: April 2026 Optimized for: Core Web Vitals, Mobile-First, SEO