Skip to content

πŸ“ˆ A comprehensive list of performance optimization techniques to improve your site's performance

Notifications You must be signed in to change notification settings

flowforfrank/performance-checklist

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

7 Commits
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

Performance Checklist

πŸ“ˆ The Performance Checklist is a comprehensive list of performance optimization techniques to improve your site's performance, and with it, its user experience. πŸ†™
β€œPremature optimization is the root of all evil” - Donald Knuth

Learn more about JavaScript and web development Follow on Twitter Follow on Medium
Support on Buy Me A Coffee
β€’ β€’ β€’
πŸ•΅οΈ SEO Checklist

πŸ—ƒοΈ Table of Contents

  1. πŸ› οΈ Tools
    1.1. Built-in Tools

    1.2. Online Tools

    1.3. Chrome Extensions

  2. πŸ—οΈ HTML Optimization
    2.1. Write Valid and Readable DOM
    2.2. Don't Use Inline Styles and Scripts
    2.3. Inline Critical CSS
    2.4. Place Script Tags at the Bottom
    2.5. Avoid Using Plugins
    2.6. Reduce the Number of DOM Elements
    2.7. Compress HTML

  3. πŸ–οΈ CSS Optimization
    3.1. Reconsider if you really need a framework
    3.2. Prefer Using a CSS Methodology
    3.3. Use Markup Instead of CSS
    3.4. Use Shorthand Properties
    3.5. Reduce Redundancy
    3.6. Avoid Complex Selectors
    3.7. Use Mobile First
    3.8. Compress CSS

  4. πŸ‘¨β€πŸ’» JavaScript Optimization
    4.1. Defer JavaScript Files
    4.2. Update Libraries
    4.3. Use Web Workers
    4.4. Eliminate Long-running Tasks
    4.5. Use the Coverage Drawer
    4.6. Avoid Micro-Optimization
    4.7. Compress JavaScript

  5. πŸ–ΌοΈ Image Optimization
    5.1. Replace Images
    5.2. Use Vector Images
    5.3. Minify SVG Markup
    5.4. Choose the Right Raster Format
    5.5. Scale Your Images
    5.6. Lazy Load Images
    5.7. Compress Images

  6. πŸ—› Font Optimization
    6.1. Minimize Number of Font Use
    6.2. Subset Fonts
    6.3. Implement Custom Font-loading Strategies
    6.4. Cache Fonts
    6.5. Compress Fonts

  7. πŸ—„οΈ Server Optimization
    7.1. Configure Compression
    7.2. Minimize the Number of HTTP Requests
    7.3. Use a CDN
    7.4. Use a Cache-Control Header

  8. πŸ‡Ό Core Web Vitals
    8.1. Largest Contentful Paint
    8.2. First Input Delay
    8.3. Cumulative Layout Shift
    8.4. How to Measure Core Web Vitals

  9. βš›οΈ Frameworks
    9.1. React Optimization Techniques

  10. πŸ“š Other Resources

πŸ› οΈ Tools

ℹ️ If you can't measure it, you can't improve it - Before you make any changes, the first step is to measure performance. This way, you will have a baseline and you can make comparisons later on. Never make performance optimizations, without first creating a baseline.

πŸ†“ The tools listed below are free to use

Built-in Tools

ℹ️ Built-in tools will be your first station in improving performance. If you don't find a certain tab in DevTools, you can open the tools pane by hitting ctrl + shift + p.

πŸ› οΈ Lighthouse

Lighthouse will be one of your best friends for performance audits. It is built into Chrome's DevTools, and can create audits for performance, accessibility, progressive web apps, SEO and more. If you don't happen to find the audit you are looking for your specific use case, it also lets you create your own plugins.

The generated audit also contain further resources for explanation of failed audits, and steps on how to resolve them.

πŸ“– GitHub - Plugin Handbook


πŸ› οΈ Network Tab

Use the Network tab to identify issues related to network requests. These can be things like:

  • Long server response times
  • Verify resources are compressed
  • Identifying large resource sizes
  • Making sure resources are downloaded or uploaded correctly

You can also use the Network tab to simulate slow network connection, or even simulate offline state.

πŸ“– Chrome DevTools - Inspect Network Activity In Chrome DevTools

Enable throttling


πŸ› οΈ Performance Tab

The performance tab is where you can identify most of the issues related to performance, such as:

  • FPS drops
  • High CPU usage
  • Memory leaks
  • Long running JavaScript tasks
  • Forced reflows

The performance tab also shows you the time frame of different key events and core web vitals, such as First Paint, First Contentful Paint, Largest Contentful Paint, DOMContentLoaded event, or the Onload event.

πŸ“– Chrome DevTools - Get Started With Analyzing Runtime Performance
πŸ“– Chrome DevTools - Performance Analysis Reference


πŸ› οΈ Memory Tab

If you suspect your application has memory leaks, this is where you can:

  • Create heap snapshots
  • Record memory usage over time

To identify the root cause of the problem. If you experience one of the followings, it is likely you have memory leaks.

  • Slow load times
  • Sluggish performance
  • The performance of the application degrades over time
  • High memory usage

πŸ“– Chrome DevTools - How to Record Heap Snapshots
πŸ“– Chrome DevTools - Fix Memory Problems


πŸ› οΈ Layers Panel

The Layers panel can help you visualize different layers on your website and identify, if:

  • You have too many layers
  • You can prevent repaint of large areas by promoting them to new composite layers

You also get to know the reason for having elements on different layers.

πŸ“– LogRocket - Eliminate content repaints with the new Layers panel in Chrome

The visuals of the Layers Panel


πŸ› οΈ Coverage Drawer

The Coverage drawer in Chrome DevTools can help you find unused JavaScript and CSS. Removing them can speed up your page load and reduce the number of bytes transferred.

❗ When you are doing analysis, make sure you interact with the page before deeming a piece of code "unused".

Anything that is shown in red inside the Coverage drawer can be potentially deferred to speed up initial page load.

πŸ“– Find Unused JavaScript And CSS Code With The Coverage Tab In Chrome DevTools


πŸ› οΈ Issues Drawer

The Issues drawer aims to combine common issues in your Console tab, to de-clutter it. It aggregates similar issues and provides resources with actions on how to resolve them.


πŸ› οΈ Rendering Drawer

The Rendering drawer lets you identify issues related to rendering. With the rendering drawer, you have the ability to:

  • Highlight areas of the page that needs to be repainted
  • Highlight areas of the page that were shifted
  • Highlight ad frames
  • Show layer borders
  • Show FPS
  • Show scrolling performance issues
  • Show borders around hit-test regions

You also have the ability to emulate different types of media type β€” such as print or screen β€” and different vision deficiencies:

  • Blurred vision
  • Protanopia
  • Deuteranopia
  • Tritanopia
  • Achromatopsia

πŸ› οΈ Request Blocking Drawer

With the Request Blocking drawer, you have the ability to block certain requests using text patterns, to simulate issues related to network requests.


Online Tools

ℹ️ Online tools give you additional help to address performance issues.

πŸ“ˆ Webhint

Webhint provides you with deep details not only on performance but other aspects as well, such as common pitfalls or security issues.

  • You can run your audits through its official website
  • You can use it in VS Code
  • You can use it as a browser extension
  • You can even integrate it into your release process through CLI

It also gives you the ability to write and enforce your own set of rules.


PageSpeed Insights is the browser version of Lighthouse. It can generate audits for you for both Mobile and Desktop with Core Web Vitals being reported at the very top.


πŸ“ˆ Web.dev

Web.dev, generates a similar report to Lighthouse. Identify performance, accessibility, best practices, or SEO problems with your site. See issues with the highest impact on the top of your report.

Report generated on Web.dev


πŸ“ˆ Bundlephobia

Bundlephobia lets you find out the real cost of adding npm packages to your bundle, by analyzing the bundle size of each package. You can generate a report by dropping your package.json file into the tool. This will generate a report for each package used, how much it adds to your load time, and what is the total cost of all packages combined.

A generated report from Bundlephobia


πŸ“ˆ GTMetrix

GTmetrix helps you discover performance issues and provides you with optimization opportunities. It generates a report for you with the most impactful issues at the top.

Report generated by GTMetrix


πŸ“ˆ WebPageTest

WebPageTest categorizes your site from A to F in the following metrics:

  • Security score
  • First Byte Time
  • Keep-alive Enabled
  • Compress Transfer
  • Compress Images
  • Cache static content
  • Effective use of CDN

The Pingdom Website Speed Test lets you insert your URL for inspection. It analyzes page load time, gives you hint on how to improve your page's performance, and let's you find bottlenecks by giving you a detailed report.


πŸ“ˆ Varvy

The Varvy SEO tools are now unavailable due to their legacy nature. We're hoping to get them back sometime in the future.


πŸ“ˆ DebugBear

DebugBear analyzes your website performance and generates a detailed report:

  • Request Waterfall
  • Automatic page speed recommendations
  • Real user Core Web Vitals data from Google
  • Lighthouse report

Chrome Extensions

ℹ️ Chrome extensions can help you enhance your workflow by providing some additional debugging tools on top of Chrome DevTools

This Chrome extension is an essential tool for any React developer. It adds two additional tabs to your Chrome DevTools:

  • βš›οΈ Components: Shows you the rendered components tree, with information on each component's props and state.
  • βš›οΈ Profiler: The Profile tab lets you record performance information for React components to easily identify unnecessary renders that may cause slow performance.

πŸ’» Web Vitals

This Chrome extension measures Core Web Vitals, providing instant feedback on loading, interactivity and layout shift metrics. It reports the same metrics you find in Lighthouse, Page Speed Insights, or Search Console.


πŸ—οΈ HTML Optimization

ℹ️ Optimizing HTML is often overlooked. However, it is a core part of any web application, therefore you should take good care of it, just as you do for other assets.

β˜‘οΈ Write Valid and Readable DOM

This include steps that not only helps in terms of performance, but also creates a more dev friendly environment:

  • Write in all lowercase: Every tag should be lowercase, so please don't use any uppercase in HTML tags.
  • Indentation is key to readability: Use it to avoid a flat, cluttered document. Enhancing readability also means it reduces development time.
  • Close self-closing tags: This was once mandatory. With HTML5 it’s optional and purely up to the developer. Either use it on all tags or don’t use it at all. The key here is being consistent.
  • Avoid overusing comments: Unless you have a build system in place or you are using a template engine, these can add up and increase the weight of your HTML file.
  • Organize DOM: Always consider if you need that extra div or extra element. Try to create only the absolute necessary ones and divide only large parts of your page with not divs, but semantic HTML elements.

β˜‘οΈ Don't Use Inline Styles and Scripts

Always use external stylesheets. Also, try to avoid using import statements in your CSS files. They produce extra server requests. Also make sure you bundle files together to reduce the number of network requests. If bundle size is a problem for you, you can split them up into 2-4 smaller chunks and take advantage of domain sharding

πŸ“– MDN Web Docs - Domain Sharding


β˜‘οΈ Inline Critical CSS

Critical CSS refers to the minimum set of CSS that is required to render the top of your page, a user sees first when landing on your site. Consider inlining critical CSS. By doing so, users will get to see the first portion of your page rendered more quickly. (Critical CSS is also referred to as β€œabove the fold” CSS)

Critical CSS


β˜‘οΈ Place Script Tags at the Bottom

This way, all the content of the body will get loaded in, before you load the content of the script tag. In return, you can trick your users into believing that your page is loading faster than it actually is.

You can also add a defer tag to your script tags to make sure the HTML gets loaded first. To get a good grasp on what is the difference between a normal, and an async vs defer script tag, take a look at the following example:

The difference between async and defer script tags


β˜‘οΈ Avoid Using Plugins

Search engines can't index plugin content, and many devices restrict plugins or don't support them. Therefore it's better to leave them out and cut down on some precious bytes.

Elements such as embed, object or applet are checked and if their MIME type matches any of the following:

  • application/x-java-applet
  • application/x-java-bean
  • application/x-shockwave-flash
  • application/x-silverlight
  • application/x-silverlight-2

Then it will be flagged as a plugin.

πŸ“– Web.dev - Document avoids plugins


β˜‘οΈ Reduce the Number of DOM Elements

Monitor the number of DOM elements present on your page. Make sure you don't:

  • Have more than 1500 DOM nodes
  • Have a depth greater than 32 nodes
  • Have a parent node with more than 60 children

Having excessive amount of DOM nodes on your page can affect performance in a number of ways:

  • Slow down initial page load time
  • Slow down rendering performance
  • Can cause heavy memory usage

πŸ“– Web.dev - Avoid an excessive DOM size

// The fastest way to count the number of DOM nodes on your site
// is using the all (*) query selector
document.querySelectorAll('*').length;

β˜‘οΈ Compress HTML

Compress your HTML to further reduce file sizes, after you've validated them. You can use third party libraries, build tools, bundlers or online applications for this.

πŸ› οΈ W3C - Markup Validation Service
πŸ› οΈ NPMJS - HTMLMinifier
πŸ› οΈ Webpack
πŸ› οΈ HTML Minifier


πŸ–οΈ CSS Optimization

ℹ️ CSS may seem like an unusual choice for performance optimization, however taking good care of your CSS assets can come a long way, as little repetitions do add up.

β˜‘οΈ Reconsider if you really need a framework

There are now many lightweight alternatives to robust frameworks. Usually, you won’t be using every selector from a framework, so your bundle will contain dead code. you can identify unused CSS rules using code coverage in DevTools.

Coverage Tab in Chrome's DevTools


β˜‘οΈ Prefer Using a CSS Methodology

CSS methodologies helps you to create consistency and modularity across your CSS files, which can lead to leaner file sizes. Some popular CSS methodologies are:

πŸ“– BEM - (Block, Element, Modifier)
πŸ“– ITCSS - (Inverted Triangle CSS)
πŸ“– OOCSS - (Object-oriented CSS)


β˜‘οΈ Use Markup Instead of CSS

You can reduce the size of your CSS bundles by simply using correct HTML elements.

/* πŸ”΄ Instead of resetting styles */
span.heading {
    display: block;
    font-size: 1.2em;
    margin-top: 1em;
    margin-bottom: 1em; 
}

/* βœ… Use a heading */
h1 { ... }

β˜‘οΈ Use Shorthand Properties

To further reduce the number of rules, always try to go with shorthand properties with margins, paddings, borders, or backgrounds.

πŸ“– MDN Web Docs - Shorthand properties

Using CSS Shorthand Properties


β˜‘οΈ Reduce Redundancy

Sometimes it’s hard to spot redundancy, especially when repeating rules don’t follow the same order in both selectors. If your classes differ in just one or two rules, it’s better to outsource those rules and use them as an extra class.

<!-- πŸ”΄ Instead of -->
<style>
    .warning {
        width: 100%;
        height: 50px;
        background: yellow;
        border-radius: 5px;
    }

    .elevated-warning {
        width: 100%;
        height: 50px;
        font-size: 150%;
        background: yellow;
        box-shadow: 1px 2px 5px #CCC;
        border-radius: 5px;
    }
</style>

<div class="warning">⚠️</div>
<div class="elevated-warning">🚨</div>
<!-- βœ… Do -->
<style>
    .warning {
        width: 100%;
        height: 50px;
        background: yellow;
        border-radius: 5px;
    }

    .warning--elevated {
        font-size: 150%;
        box-shadow: 1px 2px 5px #CCC;
    }
</style>

<div class="warning">⚠️</div>
<div class="warning warning--elevated">🚨</div>

β˜‘οΈ Avoid Complex Selectors

There are two major problems with using complex selectors. First, your increased specificity will not only make it harder to later rewrite existing rules, but also increase the time it takes for the browser to match selectors.


β˜‘οΈ Use Mobile First

When you are dealing with media queries, always use mobile-first. This will ensure that you mostly add extra rules to cater for large screen devices, rather than rewriting existing CSS rules. This can reduce the number of rules you end up with.

πŸ“– MDN Web Docs - Mobile first

/* πŸ”΄ Non mobile-first media query, everything below 600px will get the below styles */
@media (max-width: 600px) {
    /* your CSS rules */
}

/* βœ… Mobile-first media query, everything above 600px will get the below styles */
@media (min-width: 600px) {
    /* your CSS rules */
}

β˜‘οΈ Compress CSS

Compress your bundles to reduce their size. Compression removes comments and white spaces, so your bundles require less bandwidth to fetch. Another great way to further reduce the size of your CSSβ€Š β€”β€Šand markupβ€” is obfuscating class names. To achieve this, depending on your project setup you can:

Minified CSS Classnames


πŸ‘¨β€πŸ’» JavaScript Optimization

ℹ️ Bad JavaScript implementations are usually the main cause of sluggish, slow responding interfaces. When you write your JavaScript files, keep in mind the following points.

β˜‘οΈ Defer JavaScript Files

As described in the HTML section, try to defer your JavaScript assets to avoid render blocking the page. You can achieve this by moving your resources to the bottom of the page and placing them before the closing of your body tag. You can also defer non critical resources by using the async or defer attributes.

<!-- πŸ”΄Instead of -->
    ...
    <script src="app.js"></script>
</head>

<!-- βœ… Do -->
    ...
    <script src="app.js"></script>

    <!-- Also try to make use of `async` /` defer` tags -->
    <script src="app.js" async></script>
    <script src="app.js" defer></script>
</body>

β˜‘οΈ Update Libraries

Make sure your dependencies are all updated. This not only helps improve the security on your page by patching common security vulnerabilities for packages, but may also improve the size of your bundles. To know what is the real cost of your node_modules for your project setup, you can use Bundlephobia.

πŸ› οΈ Bundlephobia


β˜‘οΈ Use Web Workers

Use web workers for complex calculations. JavaScript runs on the main thread in the browser. This means that long-running tasks can freeze up the page and block user interaction. If you have heavy computational work to do, do it inside a web worker. They run on a separate thread and are non-blocking.

Note: You don’t have access to the DOM inside a web worker.


β˜‘οΈ Eliminate Long-running Tasks

Long-running JavaScript tasks are usually behind input delays. You can identify them through profiling your page with DevTools' Performance Tab. Anything shown in the stack with a red triangle is a long-running task that could be refactored to take less time to process.

πŸ“– MDN Web Docs - Intensive JavaScript

Long-running JavaScript Tasks


β˜‘οΈ Use the Coverage Drawer

The coverage tab can be a powerful tool to see which code you truly need during page load. Anything that you see in red on the image below, is not executed right away. This means you can potentially defer and request it after loading has finished.

JavaScript Code Coverage


β˜‘οΈ Avoid Micro-Optimization

It may sound tempting to optimize every bit of your code, but you’ll only save a fraction of a millisecond by doing so, and you may end up sacrificing readability and maintainability for performance. Only break this rule if you are making video games or computation-heavy applications, where every bit counts.


β˜‘οΈ Compress JavaScript

Just as for HTML and CSS, make sure you always minify, and also obfuscate your JavaScript code to add a little bit of security to your page. You should do this as part of your build process.

πŸ› οΈ JavaScript Minifier
πŸ› οΈ JSCompress
πŸ› οΈ Minify


πŸ–ΌοΈ Image Optimization

ℹ️ Most of the time, images account for most transferred bytes, meaning you can gain the most on performance by optimizing them. To start doing so, you need to know where and what types of images you are using.

β˜‘οΈ Replace Images

Some images can be removed and replaced by utilizing CSS effects. These include things like:

  • Drop shadows
  • Triangular shaped objects, arrows
  • Tooltips
  • Speech bubbles
  • Toggles and other more complex UI handlers

If you need to display text on images, use web fonts instead of encoding them into the image itself. This helps reduce resource size.


β˜‘οΈ Use Vector Images

Whenever you’re using a combination of different geometric shapes in your images, prefer using vector instead of raster. Vector images are resolution- and scale-independent making them a good choice in a world with high resolution and different screen size devices. Note the difference between the two:

πŸ“– Shutterstock - Raster vs. Vector: What’s the Difference and When to Use Which

The difference between vector and raster images


β˜‘οΈ Minify SVG Markup

The XML markup that makes up an SVG often contains unnecessary metadata added by applications that generate them. These can be safely removed to ensure you are only delivering the absolutely necessary pieces and nothing more.

πŸ“– CSS Tricks - Tools for Optimizing SVG


β˜‘οΈ Choose the Right Raster Format

Picking the right raster image format is essential to get precious bytes saved. To choose which format is best for you, go over these questions:

  1. "Do I need animations?" πŸ‘‰ go with GIF
  2. "Do I need transparency? πŸ‘‰ go with PNG-8/24
  3. "Do I need to preserve fine details?" πŸ‘‰ go with PNG-8/24, else go with JPG
  4. "Do I have more than 256 colors in my palette?" πŸ‘‰ go with PNG-24
  5. Otherwise, go with PNG-8

How to choose the right raster format


β˜‘οΈ Scale Your Images

Resize your images and ensure that the display size is as close to the natural size of the image as possible. If you are displaying a 300x150px image on your site, there’s no need for it to be 1500x750.

You can also use a srcset to display responsive images, and ensure that your images are as close to the device's display size as possible.

πŸ“– MDN web docs - Responsive images

Natural (intrinsic) vs display size of the image shown in DevTools

<!-- Use `srcset` with sizes to display different images based on screen size -->

<img srcset="small-nickcage.jpg 320w,
             medium-nickcage.jpg 768w,
             large-nickcage.jpg 1024w"
     sizes="(max-width: 320px) 280px,
            (max-width: 768px) 720px,
            1024px"
     src="large-nickcage.jpg"
alt="No need for introduction, you already know him" />

β˜‘οΈ Lazy Load Images

Many images are off-screen initially, so there’s no point in downloading every single one of them upfront. By lazy loading them, you can reduce initial page load and enhance performance. Especially on websites that are content-heavy, like image galleries or social networks based around image posts.

You can set the loading attribute to lazy in HTML to natively lazy load images where the browser supports it. For older browsers, you can provide a fallback solution, such as using the IntersectionObserver API.

πŸ“– Webtips.dev - How to Lazy Load Images Natively
πŸ“– Webtips.dev - How to Lazy Load Images With Intersection Observer

<!-- 
    Lazy-loading an image natively.
    Whenever the image comes close to the viewport, a request will be made to fetch the image.
--->
<img src="http://place-puppy.com/500x500" loading="lazy" />
// Make sure you provide fallback for browsers that do not support the `loading` attribute.
if ('loading' in HTMLImageElement.prototype) { 
    // This means the browser supports lazy-loading natively, you are good to go
} else {
    // This means the browser does not support lazy-loading natively
}

β˜‘οΈ Compress Images

Just like SVGs, many raster images contain metadata like camera information or even geolocation. These can be safely removed.

Apart from removing meta information, you can further reduce file size with lossy compression. Due to the way of how our eyes work, you can reduce resolution without noticing a difference.

πŸ› οΈ TinyPNG


πŸ—› Font Optimization

ℹ️ Just like for images, in order to know where you can make improvements, you need to first monitor your font usage, although the techniques mentioned here apply to all fonts.

β˜‘οΈ Minimize Number of Font Use

The simplest and easiest to implement is minimizing the number of fonts used on a page and the number of variants used for each font family. This not only helps in terms of performance, but also creates a more consistent design, making way for better user experience.

You can experiment with font load times on Google Fonts.

Font load time shown on Google Fonts


β˜‘οΈ Subset Fonts

Many fonts come with a wide range of glyphs that you will probably never use. If your site is made of only Latin characters, there’s no point in keeping Cyrillic glyphs in your font sets. These fonts can be subset and only include the required Unicode range to further reduce file size.

πŸ› οΈ NPMJS - Glyphhanger
πŸ› οΈ Transfonter
πŸ› οΈ Font Subsetter


β˜‘οΈ Implement Custom Font-loading Strategies

By default, font requests are put aside, until the render tree is constructed, meaning we have both DOM and CSSOM ready. This can result in delayed text rendering. By using rel="preload", you can tell the browser to treat the resource with high priority, so fonts can be requested early on.

πŸ“– CSS Tricks - A Comprehensive Guide to Font Loading Strategies
πŸ“– Web.dev - Preload key requests

<!-- Make sure to also specify the type of resource with the `as` attribute -->
<link rel="preload" href="myCustomFont.woff2" as="font" />

β˜‘οΈ Cache Fonts

Fonts are static resources. Most of the time, they rarely change, meaning you can provide a long Cache-Control: max-age directive to have them cached and avoid unnecessary network requests.


β˜‘οΈ Compress Fonts

Some font formats such as EOT or TTF are not compressed by default. Make sure to apply some kind of compression to them.

πŸ› οΈ Font Squirrel - Webfont Generator


πŸ—„οΈ Server Optimization

ℹ️ You can make huge improvements, even before your web app receives your assets.

β˜‘οΈ Configure Compression

If you haven’t already, enable server-side compression. This reduces the size of HTTP responses and has the most impact. To see which type of compression your server supports, go to the "Network" tab in DevTools. Inspect the Accept-Encoding header in a request and you’ll see all available options.

According to a benchmark test done by Akamai, brotli outperformed gzip by a median of 21%.

πŸ“– Akamai - Understanding Brotli's Potential

Accept-Encoding Request Header


β˜‘οΈ Minimize the Number of HTTP Requests

While compression can save significant amounts of data, you can further cut down page load times by minimizing the number of HTTP requests. Some common techniques are:

  • Bundling your assets
  • If bundle sizes are too large, you can make use of domain sharding and split them to smaller chunks
  • Use image sprites for CSS

πŸ“– MDN Web Docs - Domain Sharding


β˜‘οΈ Use a CDN

Content delivery network can help you reduce response times. A CDN is a collection of servers distributed across the globe. It aims to help deliver content to users faster by choosing the server closest to the user’s location.

πŸ“– Akamai - What does CDN stand for? CDN Definition


β˜‘οΈ Use a Cache-Control Header

Cache each resource to avoid unnecessary network trips.

  • For static assets that rarely change (images, fonts): use a long expiry date
  • For other resources (JavaScript, CSS): use an appropriate Cache-Control header

πŸ“– KeyCDN - How to Propertyl Configure Cache-Control
πŸ“– MDN Web Docs - Cache-Control


ℹ️ Metrics that focus on three aspects of the user experience; loading, interactivity, and visual stability. They aim to quantify user experience, by introducing the below performance metrics

β˜‘οΈ Largest Contentful Paint

LCP for short, measures the time it takes for the browser to fully render the main content of your page. LCP is considered good when it happens within 2.5 seconds.

❓ What are the main causes?

  • Slow server response times
  • Slow resource loading
  • Render blocking elements

❓ How can you resolve them?

  • Optimize your server-side
  • Cut down the number of network requests
  • Lazy load offscreen resources
  • Defer render blocking assets

πŸ“– Web.dev - Largest Contentful Paint (LCP)
πŸ“– Webtips.dev - Core Web Vitals: Loading


β˜‘οΈ First Input Delay

FID for short, measures the time it takes for the first user input to be processed. Anything below 100ms is considered good.

❓ What are the main causes?

  • Long-running JavaScript tasks
  • Slow resource times
  • Render blocking elements

❓ How can you resolve them?

  • Eliminate long-running JavaScript tasks, that you can identify through DevTools' Performance tab
  • Defer render blocking assets

πŸ“– Web.dev - First Input Delay (FID)
πŸ“– Webtips.dev - Core Web Vitals: Interactivity


β˜‘οΈ Cumulative Layout Shift

CLS for short, measures the amount of layout shifts on your page that causes elements to change position unexpectedly. A good CLS score is less than 0.1.

❓ What are the main causes?

  • Images with no dimensions
  • Dynamically rendered content
  • Web fonts causing FOIT or FOUT
  • Bad state management (can be counted as dynamically rendered content)

❓ How can you resolve them?

  • Define a width and height property for images
  • Use srcset to display different resolution images for different devices
  • Always try to inject dynamic content below already existing content
  • If you use ads, define a fix size for them to reserve space

πŸ“– Web.dev - Cumulative Layout Shift (CLS)
πŸ“– Webtips.dev - Core Web Vitals: Visual Stability


β˜‘οΈ How to Measure Core Web Vitals?

If you can't measure it, you don't know where to improve. Some tools that you can use for audits are listed below.

πŸ› οΈ Lighthouse - An open-source, automated tool for improving the quality of web pages.
πŸ› οΈ DevTools Performance Tab - Get Started With Analyzing Runtime Performance
πŸ› οΈ Goolge's PageSpeed Insight Tool - Generate the same Lighthouse report you would get from Chrome's DevTools
πŸ› οΈ Google's Search Console - Measures your site's search traffic and performance, and shows which pages needs your attention for optimization
πŸ› οΈ Web Vitals Chrome Extension - Chrome extension created for reporting core web vital scores


βš›οΈ Frameworks

ℹ️ JavaScript Frameworks deserves a whole section on its own, as each can come with performance best practices on top of vanilla JavaScript.

React Optimization Techniques

ℹ️ A component-based declarative JavaScript Library for building user interfaces both on the web and mobile.

β˜‘οΈ Use Production Build

By default, React includes many helpful warnings. These warnings are very useful in development. However, they make React larger and slower so you should make sure to use the production version when you deploy the app.

πŸ“– React.org - Use the Production Build


β˜‘οΈ Profile Components

Using either DevTools' built in Performance Tab or the React Developer Tools Chrome extension, you can profile and visualize how components are mounted, updated and unmounted. This helps you visualize unnecessary re-renders.

πŸ“– React.org - Profiling Components with the Chrome Performance Tab


β˜‘οΈ Virtualize Long Lists

If you are rendering long lists of data, reduce render time and the number of DOM nodes created by only rendering components that are visible to the user.

πŸ“– React.org - Virtualize Long Lists
πŸ“Ί YouTube:Addy Osmani - Rendering large lists with react-virtualized or react-window


β˜‘οΈ Pre-render routes

If rendering React on your server is not an option for you, but you still want to improve the first paint of your application, you can try pre-rendering with React snap. It uses a headless browser to generate static HTML of every route during build time. These can be shipped along with your bundle to improve page load speed.

πŸ“– Web.dev - Pre-render routes with react-snap


πŸ“š Other Resources