Frontend Performance Checklist
A practical frontend performance checklist covering HTML, CSS, JavaScript, images, fonts, caching, rendering, network requests, Core Web Vitals and production optimization.
Frontend performance affects how quickly a website becomes visible, interactive and responsive to user input. A fast frontend does not depend on one optimization. It is the result of many decisions involving HTML, CSS, JavaScript, images, fonts, network requests, caching, rendering and application architecture.
This frontend performance checklist provides a practical way to review a website before and after deployment. It covers the most important areas that can increase loading time, block rendering, waste bandwidth or create a slow interaction experience.
1. Measure Performance First
Performance optimization should begin with measurement. Without a baseline, it is difficult to determine whether a change actually improved the application or simply changed one metric while making another worse.
- Test important pages on mobile and desktop.
- Measure both first visits and repeat visits.
- Test on slower network conditions.
- Check Core Web Vitals.
- Inspect the browser Network panel.
- Analyze the page waterfall.
- Identify large resources.
- Look for render-blocking resources.
- Measure JavaScript execution and long tasks.
- Repeat measurements after major optimizations.
| Metric | What It Helps Evaluate |
|---|---|
| LCP | Loading performance of the main visible content |
| INP | Responsiveness to user interactions |
| CLS | Visual stability during loading and interaction |
| TTFB | Time until the first byte of the response |
| Total transferred bytes | Amount of data downloaded |
| Long tasks | Main-thread work that can delay interaction |
2. Optimize HTML
HTML is the starting point for the browser's loading and rendering process. Excessive markup, unnecessary elements and inefficient resource references can increase parsing work and make the document harder to process.
- Keep HTML structure as simple as practical.
- Remove unnecessary elements and wrappers.
- Avoid generating extremely large documents.
- Use semantic HTML where appropriate.
- Ensure important content is present in the initial document.
- Avoid unnecessary inline data.
- Reference only required stylesheets and scripts.
- Minify production HTML.
Minification removes unnecessary whitespace and other formatting characters without changing the document's intended meaning. It does not replace good architecture, but it can reduce the number of bytes transferred for large HTML documents.
<!-- Development -->
<section>
<h2>Products</h2>
<p>Available products</p>
</section>
<!-- Production can be minified -->
<section><h2>Products</h2><p>Available products</p></section>3. Optimize CSS
CSS can affect both network transfer and rendering. Large stylesheets, unused rules and stylesheets that block the initial render can delay the time at which users see useful content.
- Remove unused CSS where practical.
- Minify production stylesheets.
- Avoid loading unnecessary CSS on every page.
- Split styles when the application benefits from it.
- Prioritize styles needed for the initial viewport.
- Avoid excessive CSS complexity.
- Avoid importing large unused libraries.
- Use appropriate media conditions for non-critical styles.
CSS can be render-blocking because the browser needs to understand applicable styles before it can safely render the page. Reducing the amount of CSS required for the initial rendering path can therefore improve perceived loading performance.
4. Optimize JavaScript
JavaScript is one of the most important frontend performance factors because downloaded code must often be parsed, compiled and executed on the main thread. A relatively small JavaScript file can still be expensive if it performs substantial work after loading.
- Remove unused JavaScript.
- Minify production bundles.
- Use code splitting.
- Lazy load non-critical features.
- Avoid shipping unnecessary dependencies.
- Analyze bundle sizes.
- Reduce expensive startup work.
- Avoid unnecessary client-side rendering.
- Defer non-critical scripts.
- Avoid repeated calculations during rendering.
// Load a feature only when it is needed
const module = await import("./heavy-feature.js");
module.initialize();Code splitting allows an application to send only the JavaScript required for the current page or feature. Additional code can be downloaded when the user actually needs it.
5. Reduce JavaScript Execution
Reducing bundle size is only part of JavaScript optimization. The browser must also execute the code. Large amounts of synchronous JavaScript can occupy the main thread and delay rendering or interaction.
- Avoid unnecessary work during application startup.
- Break large tasks into smaller tasks when appropriate.
- Avoid expensive calculations during every render.
- Use memoization only when it provides a real benefit.
- Reduce unnecessary component updates.
- Avoid large synchronous loops on the main thread.
- Move suitable heavy work away from the main thread.
- Load expensive features only when required.
6. Optimize Images
Images are frequently among the largest resources on a page. Sending images that are much larger than their displayed dimensions wastes bandwidth and increases loading time.
- Resize images to appropriate dimensions.
- Compress images.
- Use modern image formats when appropriate.
- Use responsive image techniques.
- Avoid serving desktop-sized images to small mobile displays.
- Lazy load non-critical images.
- Provide image dimensions.
- Optimize image quality for the actual use case.
- Avoid unnecessary duplicate image downloads.
| Technique | Purpose |
|---|---|
| Resize | Avoid unnecessarily large pixel dimensions |
| Compression | Reduce file size |
| Responsive images | Serve appropriate sizes to different devices |
| Lazy loading | Delay non-critical image requests |
| Dimensions | Reserve layout space |
| Modern formats | Improve encoding efficiency |
7. Lazy Load Non-Critical Images
Images below the initial viewport are often good candidates for lazy loading. Native browser lazy loading can be enabled with the loading="lazy" attribute.
<img
src="/images/article.jpg"
width="1200"
height="800"
loading="lazy"
alt="Article illustration"
/>Important above-the-fold images should not automatically be lazy loaded. If the main visible image contributes to the page's LCP, delaying it can make the initial experience slower.
8. Use Responsive Images
Responsive images allow browsers to select an appropriate image resource based on viewport dimensions and display requirements. This prevents a small device from unnecessarily downloading a very large image.
<img
src="/images/photo-1200.jpg"
srcset="
/images/photo-480.jpg 480w,
/images/photo-800.jpg 800w,
/images/photo-1200.jpg 1200w
"
sizes="(max-width: 600px) 100vw, 800px"
width="1200"
height="800"
alt="Example photo"
/>9. Optimize SVG Files
SVG is useful for logos, icons, illustrations and other vector graphics, but exported SVG files can contain unnecessary metadata, editor information, comments and redundant attributes.
- Remove unnecessary metadata.
- Remove editor-specific information.
- Reduce redundant attributes.
- Minimize path data where appropriate.
- Avoid embedding unnecessarily large resources.
- Use optimized SVG files in production.
SVG optimization should preserve the visual result while reducing unnecessary markup and data. For frequently used icons and graphics, even small savings can accumulate across many pages.
10. Optimize Fonts
Web fonts can affect both loading performance and text rendering. Large font files, too many font families and unnecessary font weights can increase network requests and delay visual completion.
- Load only required font families.
- Load only the weights actually used.
- Prefer efficient font formats.
- Subset fonts when appropriate.
- Use local or CDN delivery strategically.
- Define appropriate font-display behavior.
- Avoid loading many decorative fonts.
| Problem | Potential Improvement |
|---|---|
| Many font families | Reduce the number of families |
| Unused weights | Load only required weights |
| Large font files | Subset or optimize fonts |
| Slow font loading | Review delivery and font-display |
11. Reduce Render-Blocking Resources
Some resources can delay the browser from rendering useful content. Large CSS files and synchronous scripts are common examples. Reducing render-blocking work can improve the time users see the initial page.
- Reduce unnecessary CSS required during initial rendering.
- Defer non-critical JavaScript.
- Use async loading where appropriate.
- Avoid unnecessary third-party scripts.
- Prioritize critical resources.
- Reduce the amount of work required before first rendering.
<script src="/analytics.js" defer></script>The async and defer attributes have different loading and execution behavior, so they should be selected according to the script's dependencies. Scripts required to construct the initial page should not be deferred without understanding the consequences.
12. Optimize the Critical Rendering Path
The critical rendering path includes the work required to transform HTML, CSS and other required resources into pixels on the screen. The goal is to minimize unnecessary work and prioritize resources needed for the initial viewport.
HTML
β
DOM
β
CSS
β
CSSOM
β
Render Tree
β
Layout
β
Paint
β
Composite- Reduce HTML size.
- Reduce critical CSS.
- Prioritize important resources.
- Defer non-critical JavaScript.
- Avoid unnecessary rendering work.
- Optimize the main LCP resource.
13. Improve Time to First Byte
Frontend performance is affected by the time required to receive the initial document. A slow server response delays everything that follows, including HTML parsing, resource discovery and rendering.
- Optimize server-side processing.
- Use appropriate caching.
- Use a CDN when appropriate.
- Reduce unnecessary database work.
- Avoid excessive middleware processing.
- Use efficient hosting infrastructure.
- Measure backend response time separately from frontend work.
A page with highly optimized CSS and JavaScript can still feel slow if the initial HTML response takes a long time to arrive. Performance optimization should therefore consider the complete request lifecycle rather than only browser-side code.
14. Use Browser Caching
Caching allows browsers to reuse resources that were already downloaded. Static assets such as versioned CSS, JavaScript, images and fonts can often use long cache lifetimes when their URLs change whenever their content changes.
Cache-Control: public, max-age=31536000, immutable- Use long-lived caching for versioned static assets.
- Use content hashes where appropriate.
- Choose suitable policies for HTML.
- Use validation for resources that change regularly.
- Avoid long caching for unversioned frequently changing files.
15. Use a CDN Strategically
A content delivery network can serve static resources from locations closer to users. This can reduce network distance and improve delivery times for geographically distributed audiences.
- Serve suitable static assets through a CDN.
- Configure caching correctly.
- Use versioned asset URLs.
- Check cache hit behavior.
- Avoid unnecessary origin requests.
- Choose CDN locations appropriate for the target audience.
16. Reduce Network Requests
Modern browsers can handle many concurrent requests, but excessive resources still create overhead. Each stylesheet, script, image, font and third-party resource can contribute to connection, parsing, processing or scheduling work.
- Remove unused resources.
- Avoid loading the same asset multiple times.
- Reduce unnecessary third-party scripts.
- Combine resources when the architecture benefits from it.
- Use efficient bundling.
- Avoid loading entire libraries for tiny features.
- Prioritize resources needed for the current page.
17. Review Third-Party Scripts
Analytics, advertising, chat widgets, social integrations and other third-party services can introduce additional network requests and JavaScript execution. They may also change independently of your application's deployment process.
- Remove third-party scripts that are no longer needed.
- Load non-critical integrations later.
- Audit third-party JavaScript regularly.
- Measure their main-thread cost.
- Avoid adding multiple tools that provide the same functionality.
- Check whether third-party resources block rendering.
18. Prevent Layout Shifts
Unexpected movement during loading makes pages harder to use and can lead to poor visual stability. Images, advertisements, embedded content and dynamically inserted elements are common sources of layout shifts.
- Set dimensions for images.
- Reserve space for embedded content.
- Reserve predictable areas for dynamic components.
- Avoid inserting content above existing content unexpectedly.
- Load fonts carefully.
- Use stable layouts for asynchronous content.
.image {
aspect-ratio: 16 / 9;
width: 100%;
}19. Optimize Interaction Performance
A page can load quickly and still feel slow if interactions trigger expensive JavaScript work. Buttons, forms, menus, filters and other interactive features should respond without blocking the main thread for long periods.
- Avoid expensive event handlers.
- Debounce high-frequency operations when appropriate.
- Throttle expensive scroll or resize processing.
- Avoid unnecessary DOM updates.
- Break up long JavaScript tasks.
- Avoid unnecessary re-renders.
- Move suitable heavy computation away from the main thread.
20. Optimize CSS Rendering
CSS can influence layout, paint and compositing. Extremely complex selectors or frequent changes to layout-related properties can increase rendering work, especially in highly interactive interfaces.
- Avoid unnecessarily complex selectors.
- Avoid frequent forced synchronous layout.
- Batch DOM and style changes where appropriate.
- Prefer efficient animation techniques.
- Use transform and opacity for suitable animations.
- Avoid animating expensive layout properties unnecessarily.
21. Optimize Animations
Animations should remain smooth while using as few expensive rendering operations as practical. Animating properties that require repeated layout or paint can be more expensive than animating properties that can be handled efficiently by the compositor.
.card {
transition: transform 200ms ease, opacity 200ms ease;
}
.card:hover {
transform: translateY(-4px);
opacity: 0.95;
}22. Review Client-Side Rendering
Client-side rendering can provide highly interactive applications, but sending a large JavaScript application before displaying meaningful content can increase startup work. For content-focused pages, server rendering or static generation may reduce the amount of work required before users see useful HTML.
- Avoid making the entire page client-rendered without a reason.
- Render static content as early as practical.
- Send interactive JavaScript only where needed.
- Use server rendering or static generation when appropriate.
- Split large client-side features.
23. Optimize Web Application Architecture
Performance should be considered at the architectural level. A page that requires a large amount of JavaScript, many API requests and multiple sequential dependencies will be difficult to optimize only through minification.
- Avoid unnecessary client-server round trips.
- Reduce request waterfalls.
- Parallelize independent data requests where appropriate.
- Cache reusable data.
- Keep page-specific code isolated.
- Use static generation for content that does not require runtime rendering.
- Avoid shipping features that users do not need.
24. Check for Request Waterfalls
A request waterfall occurs when one network request must finish before another request can begin. Long chains of dependent requests can significantly increase total loading time even when each individual request is relatively fast.
HTML
β
JavaScript
β
API request
β
Second API request
β
Image request
Potentially slower
HTML
βββ JavaScript
βββ API request
βββ Image request
βββ Font request
More parallel workIndependent resources should be allowed to load in parallel when the application architecture permits it. Reducing unnecessary dependencies between requests can improve the total loading path.
25. Optimize Production Builds
Development builds often contain debugging information, source maps, unminified code and other features that are useful during development but are not intended for production delivery.
- Use the production build configuration.
- Enable minification.
- Verify code splitting.
- Remove development-only code.
- Analyze generated bundles.
- Check final asset sizes.
- Verify compression is enabled.
- Verify caching headers.
26. Enable Compression
Text-based resources such as HTML, CSS and JavaScript can often be compressed significantly before being transferred over the network. Compression reduces transferred bytes and can improve loading speed, particularly on slower connections.
| Resource | Compression Consideration |
|---|---|
| HTML | Highly compressible |
| CSS | Highly compressible |
| JavaScript | Highly compressible |
| SVG | Often highly compressible |
| JPEG/WebP/AVIF | Already compressed image formats |
| PNG | Compressed image format; optimization may still help |
27. Use Resource Hints Carefully
Resource hints such as preload, preconnect and prefetch can help browsers establish connections or request important resources earlier. However, they should be used selectively because unnecessary hints can compete with more important resources.
- Preload only genuinely critical resources.
- Use preconnect for important external origins when justified.
- Use prefetch for resources likely to be needed later.
- Avoid preloading large numbers of resources.
- Verify that resource hints improve actual performance.
28. Audit Dependencies
Frontend dependencies can add significant JavaScript, CSS or runtime overhead. A package may be convenient but unnecessarily large for a small feature, especially when only a fraction of its functionality is used.
- Remove unused dependencies.
- Review large packages.
- Check whether smaller alternatives exist.
- Import only required functionality where supported.
- Avoid duplicate libraries that solve the same problem.
- Review dependencies after major feature changes.
29. Build a Performance Budget
A performance budget defines practical limits for resources such as JavaScript, CSS, images and total transferred bytes. Without a budget, an application can gradually become slower as new features and dependencies are added.
| Budget Area | Example Goal |
|---|---|
| JavaScript | Keep initial bundle within a defined limit |
| CSS | Limit critical stylesheet size |
| Images | Restrict initial image bytes |
| Requests | Avoid unnecessary initial requests |
| Third-party code | Limit external scripts |
30. Final Production Checklist
Before releasing a frontend application, review the most important performance areas together rather than checking them independently. A fast page usually combines optimized assets, efficient rendering, appropriate caching and minimal unnecessary work.
- Measure Core Web Vitals.
- Check LCP and identify the main LCP element.
- Check INP and interaction responsiveness.
- Check CLS and layout stability.
- Measure TTFB.
- Minify HTML.
- Minify CSS.
- Minify JavaScript.
- Remove unused CSS and JavaScript.
- Split large JavaScript bundles.
- Optimize images.
- Use responsive image delivery.
- Lazy load non-critical images.
- Reserve space for images and embeds.
- Optimize SVG files.
- Reduce unnecessary font files and weights.
- Defer non-critical JavaScript.
- Review render-blocking resources.
- Reduce third-party scripts.
- Enable compression.
- Configure browser caching.
- Use long-lived caching for versioned assets.
- Use a CDN where appropriate.
- Check for request waterfalls.
- Review production bundle sizes.
- Audit dependencies.
- Test on mobile devices.
- Test on slower connections.
- Compare performance before and after optimization.
Performance Checklist by Priority
Not every optimization has the same impact. When time is limited, start with the problems that affect the initial loading path and the largest resources. Optimizing a tiny asset is unlikely to matter if the page is sending a huge image or executing a large JavaScript bundle.
| Priority | Focus Areas |
|---|---|
| High | LCP, large images, JavaScript execution, render-blocking resources, TTFB |
| Medium | Fonts, CSS size, caching, third-party scripts, request waterfalls |
| Lower | Minor markup savings, small asset optimizations, low-impact micro-optimizations |
Common Frontend Performance Mistakes
- Optimizing before measuring.
- Focusing only on Lighthouse scores.
- Lazy loading critical images.
- Shipping unnecessarily large JavaScript bundles.
- Serving oversized images.
- Ignoring mobile performance.
- Loading too many third-party scripts.
- Using long cache lifetimes for unversioned assets.
- Ignoring layout shifts.
- Assuming minification alone makes a frontend fast.
- Adding performance features without measuring their effect.
Frequently Asked Questions
What is the most important frontend performance optimization?
There is no single optimization that is best for every website. Large images, JavaScript execution, render-blocking resources, slow server responses and other bottlenecks can dominate depending on the application. Measure the page first and address the largest problems.
Does minifying HTML, CSS and JavaScript improve performance?
Yes, minification can reduce transferred file sizes by removing unnecessary characters. However, it is only one part of frontend optimization and does not solve problems such as excessive JavaScript execution, oversized images or slow server responses.
Should all images be lazy loaded?
No. Images below the initial viewport are good candidates for lazy loading, while important above-the-fold images should generally remain prioritized.
How can I improve LCP?
Start by identifying the LCP element. Depending on the page, improvements can include reducing TTFB, prioritizing the LCP resource, optimizing its image or font, reducing render-blocking resources and minimizing unnecessary work before rendering.
Why is my website slow even though the JavaScript bundle is small?
Bundle size is only one factor. Slow TTFB, large images, render-blocking CSS, third-party scripts, request waterfalls, expensive runtime work or layout problems can still make the page slow.
Does a CDN automatically make a website faster?
A CDN can improve asset delivery by serving resources from locations closer to users, but it does not automatically optimize the assets or application. Cache configuration, resource size and origin performance still matter.
How often should frontend performance be checked?
Performance should be checked during development, before important releases and after major changes. Continuous monitoring is useful for production applications because new features and dependencies can introduce regressions.
Helpful Frontend Performance Tools
An HTML Minifier reduces unnecessary characters in production HTML, a CSS Minifier compresses stylesheets, a JS Minifier reduces JavaScript file size, an SVG Optimizer removes unnecessary SVG data, and a Responsive Image Size Calculator helps determine appropriate image dimensions for different display sizes.
Conclusion
Frontend performance is the result of many small and large engineering decisions. Efficient HTML, optimized CSS and JavaScript, properly sized images, responsive image delivery, sensible lazy loading, efficient fonts, caching, compression and careful rendering all contribute to a faster user experience.
The most effective workflow is to measure first, identify the largest bottleneck, make a targeted change and measure again. By combining this process with a repeatable performance checklist, developers can prevent regressions and keep applications fast as their feature set grows.