| Eliminate render-blocking resources | • Inline critical resources
• Defer non-critical resources
• Remove resources which are not used on the page |
| --- | --- |
| Images | • Properly size images
◦ Resize images to save data
◦ Image should not be larger than the version rendered on screen
◦ Serve responsive images
◦ Use an image CDN
◦ Replace complex icons with SVG
• Set an explicit width and height on image elements to reduce layout shifts and improve CLS
• Defer offscreen images
◦ Consider lazy-loading offscreen and hidden images after critical resources have loaded
• Efficiently encode images
◦ Optimize images either manually or through an automated optimization process with every upload
• Serve images in next-gen formats
◦ Choose WebP or AVIF instead of PNG or JPEG for your images for better compression, faster downloads and less data consumption |
| Minify CSS or remove unused CSS | • Minify CSS through an automated workflow
• Remove identified unused CSS |
| Minify JavaScript | • Minify JavaScript to reduce payload sizes and script parse time
• Remove whitespace and any unnecessary code from the JS code file |
| Enable text compression | • Enable text compression on your server
• Use tools like gzip, Deflate or Brotli to compress text-based resources |
| Preconnect to required origins | • Establish early connections to third-party origins with preconnect and dns-prefetch |
| Reduce server response times (TTFB) | • Optimize your server response time by optimizing core conceptual tasks |
| Avoid multiple page redirects | • Avoid redirects in resources required for your critical rendering path
• Try to avoid redirecting users to a mobile version of your page
• Opt for a responsive page instead |
| Preload key requests | • Identify critical resources and instruct the browsers to download key resources as soon as possible via preload links in HTML
• Consider using <link rel=preload>
to prioritize fetching resources that are currently requested later in page load |
| Use video format for animated content | • Avoid using large GIF formats for website video/animated content
• Convert GIFs into video in loop in MPEG4/WebM
• Opt for PNG/WebP for static images instead of GIF
• Convert GIFs into HTML5 videos using https://web.dev/image-cdns/ |
| Reduce impact of third-party code | • Identify slow third-party code and optimize
• Limit the number of redundant third-party providers and try to load third-party code after your page has primarily finished loading |
| Avoid non-composited animations | • See Stick to compositor-only properties and manage layer count and High-performance animations
• Animations which are not composited can be janky and increase CLS |
| Lazy load third-party resources with facades | • On load: add a facade
• On mouseover: preconnect the facade to third-party resources
• On click: facade is replaced with third-party product |
| Avoid high network payloads | • Aim to keep total byte size below 1600KiB
• Defer requests until needed
• Optimize requests to be as small as possible
• Cache requests |
| Serve static assets with efficient cache policy | • Cache immutable static assets for a year or longer
• Use no-cache for resources where freshness matters
• A long cache lifetime can speed up repeat visits to your page |
| Avoid excessive DOM size | • Try to aim for fewer than ~1500 DOM elements
• Try to aim for a tree depth of <32 elements and less than 60 children/parent element
• Create DOM nodes only when needed, and destroy nodes when they're no longer needed |
| Avoid chaining critical requests | • Minimize number of critical resources (eliminate, defer download, etc.)
• Optimize number of critical bytes
• Optimize order in which resources are loaded
• Consider reducing the length of chains, reducing the download size of resources, or deferring the download of unnecessary resources to improve page load |
| User Timing marks and measures | • Consider instrumenting your app with the User Timing API to measure your app's real-world performance during key user experiences
• Use the React DevTools Profiler, which makes use of the Profiler API, to measure the rendering performance of your components |
| Reduce JavaScript execution time | • Evaluate biggest contributors to execution time
• Only send code that users need by implementing code splitting
• Minify and compress code
• Remove unused code
• Reduce network trips through caching |
| Minimize main thread work | • Reduce the time spent parsing, compiling and executing JS
• Delivering smaller JS payloads helps with this
• Consider The anatomy of a frame for an overview of how Chromium renders web pages and Do less main thread work to learn how to use Chrome DevTools to investigate exactly what your main thread is doing as the page loads |
| Ensure text remains visible during webfont load | • Preload webfonts
• Google fonts
• Leverage the font-display
CSS feature to ensure text is user-visible while webfonts are loading |
| Ensure lazy load for Largest Content Ful Paint element/image | • Load images above the fold more eagerly as above-the-fold images that are lazily loaded render later in the page lifecycle, which can delay the largest contentful paint |
| Avoid long main-tread tasks | • Consider splitting up large scripts as they are often a major cause of Long Tasks
• Also keep an eye on third-party scripts; their Long Tasks can delay primary content from getting interactive |
| Avoid large layout shitfs | • Identify causes of CLS and fix issues (e.g., images without dimensions; ads, embeds, and other late-loaded content; animations; web fonts)
• Reduce CLS by ensuring pages are eligible for the bfcache |
| Use passive listeners to improve scrolling performance | • Mark touch and wheel event listeners as passive
to improve your page's scroll performance |
| Avoid document.write()
| • Remove all uses of document.write()
in your code. If it's being used to inject third-party scripts, try using asynchronous loading instead
• If third-party code is using document.write()
, ask the provider to support asynchronous loading
• For users on slow connections, external scripts dynamically injected via document.write()
can delay page load by tens of seconds |
| Use a <meta name="viewport">
tag with width
or initial-scale
| • Use a <meta name="viewport">
not only to optimize app for mobile screen sizes, but also to prevent a 300 millisecond delay to user input |