Frontend Performance Optimization: 20 Techniques for Faster Web Apps
The highest-impact frontend performance optimisations are: (1) serve images in WebP/AVIF format with correct dimensions; (2) code-split routes with React.lazy(); (3) use a CDN for all static assets; (4) implement proper HTTP caching headers; (5) defer non-critical JavaScript; (6) preconnect to third-party origins; (7) optimise LCP image (preload it explicitly); (8) remove unused CSS with PurgeCSS or Tailwind content scanning; (9) use font-display: swap for web fonts; (10) measure with Lighthouse and fix the actual bottlenecks shown.
Commercial Expertise
Need help with Web Development?
Ortem deploys dedicated High-Performance Web squads in 72 hours.
Why Frontend Performance Matters
Google's Core Web Vitals are a direct ranking factor. Slow pages rank lower. Beyond SEO, load time directly correlates with conversion: Google data shows each second of additional load time reduces conversions by 4.42%.
The good news: most performance improvements are not complex — they are consistently overlooked standard practices.
Core Web Vitals Targets (2026)
| Metric | Good | Needs Improvement | Poor |
|---|---|---|---|
| LCP (Largest Contentful Paint) | < 2.5s | 2.5s–4.0s | > 4.0s |
| INP (Interaction to Next Paint) | < 200ms | 200–500ms | > 500ms |
| CLS (Cumulative Layout Shift) | < 0.1 | 0.1–0.25 | > 0.25 |
Image Optimisation (Highest Impact)
1. Use modern formats
Convert all images to WebP (30–40% smaller than JPEG) or AVIF (50% smaller). Use <picture> with fallbacks for broad compatibility.
2. Serve correctly sized images
Never serve a 2000px image displayed at 400px. Use responsive images with srcset and sizes attributes, or use a CDN with on-the-fly image resizing (Cloudinary, Imgix, Cloudflare Images).
3. Lazy load below-the-fold images
<img loading="lazy" is native browser support — use it for every image not in the initial viewport.
4. Preload your LCP image
The Largest Contentful Paint element (usually the hero image) should be preloaded:
<link rel="preload" as="image" href="/hero.webp" fetchpriority="high">
JavaScript Optimisation
5. Code splitting per route
Every route should be a separate chunk loaded on demand. In React:
const Dashboard = React.lazy(() => import('./pages/Dashboard'));
6. Tree shake aggressively
Import only what you use. import { debounce } from 'lodash-es' (tree-shakeable) vs import _ from 'lodash' (ships entire library).
7. Defer non-critical scripts
Analytics, chat widgets, and A/B testing scripts should load after the main content:
<script src="analytics.js" defer></script>
8. Analyse your bundle
Run npx vite-bundle-visualizer or webpack-bundle-analyzer to see exactly what is in your bundle. Surprise large packages (moment.js, lodash, faker) are common.
CSS Optimisation
9. Remove unused CSS
Tailwind's content scanning eliminates unused utility classes automatically. For custom CSS, use PurgeCSS.
10. Avoid render-blocking CSS
Only the critical CSS for above-the-fold content should be in <head>. Remaining CSS can be loaded asynchronously.
Fonts
11. Use font-display: swap
Prevents invisible text during font loading:
@font-face {
font-display: swap;
}
12. Self-host fonts
Google Fonts adds an extra DNS lookup and network request. Self-host your font files on your CDN for faster delivery.
13. Subset fonts
If you only use Latin characters, subset your font file to remove unused character sets (reduces file size 60–80%).
Caching and Network
14. Use a CDN for all static assets
Static assets (JS, CSS, images) should be served from a CDN edge near the user, not from your origin server. CloudFront, Fastly, and Cloudflare are standard choices.
15. Set immutable cache headers
Assets with hashed filenames (output of Vite/Webpack build) should have Cache-Control: max-age=31536000, immutable.
16. Preconnect to critical third-party origins
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://api.yourbackend.com">
Rendering Strategy
17. Choose the right rendering model
| Need | Strategy |
|---|---|
| SEO + dynamic data | SSR (Next.js getServerSideProps) |
| SEO + mostly static | SSG (Next.js getStaticProps) |
| No SEO + rich interactivity | SPA (React + Vite) |
| Content site | Static + islands (Astro) |
18. Virtualise long lists
Rendering 1,000 list items in the DOM is expensive. Use react-window or @tanstack/virtual to render only visible items.
19. Optimise React renders
- Wrap expensive computations in
useMemo - Wrap stable callbacks in
useCallbackwhen passed to memoised children - Use
React.memofor pure components that receive stable props
20. Measure before optimising
Profile with Chrome DevTools Performance tab and Lighthouse before guessing at bottlenecks. Fix what the data tells you to fix.
Need a performance audit for your web application? Talk to our web team → or contact us to schedule a Core Web Vitals audit.
Get the Ortem Tech Digest
Monthly insights on AI, mobile, and software strategy - straight to your inbox. No spam, ever.
About the Author
Digital Marketing Head, Ortem Technologies
Mehul Parmar is the Digital Marketing Head at Ortem Technologies, leading the marketing team under the direction of Praveen Jha. A seasoned digital marketing expert with 15 years of experience and 500+ projects delivered, he specialises in SEO, SEM, SMO, Affiliate Marketing, Google Ads, and Analytics. Certified in Google Ads & Analytics, he is proficient in CMS platforms including WordPress, Shopify, Magento, and Asp.net. Mehul writes about growth marketing, search strategies, and performance campaigns for technology brands.
Stay Ahead
Get engineering insights in your inbox
Practical guides on software development, AI, and cloud. No fluff — published when it's worth your time.
Ready to Start Your Project?
Let Ortem Technologies help you build innovative solutions for your business.
You Might Also Like

