JavaScript performance optimization - Learn web development

JavaScript performance optimization
===================================

* Previous
* Overview: Performance
* Next

It is very important to consider how you are using JavaScript on your websites and think about how to mitigate any performance issues that it might be causing. While images and video account for over 70% of the bytes downloaded for the average website, byte per byte, JavaScript has a greater potential for negative performance impact — it can significantly impact download times, rendering performance, and CPU and battery usage. This article introduces tips and techniques for optimizing JavaScript to enhance the performance of your website.

|  |  |
| --- | --- |
| Prerequisites: | Basic software installed, and basic knowledge of
 client-side web technologies.
  |
| Objectives: |
 To learn about the effects of JavaScript on web performance
 and how to mitigate or fix related issues.
  |

To optimize or not to optimize
------------------------------

The first question you should answer before starting to optimize your code is "what do I need to optimize?". Some of the tips and techniques discussed below are good practices that will benefit just about any web project, whereas some are only needed in certain situations. Trying to apply all these techniques everywhere is probably unnecessary, and may be a waste of your time. You should figure out what performance optimizations are actually needed in each project.

To do this, you need to measure the performance of your site. As the previous link shows, there are several different ways to measure performance, some involving sophisticated performance APIs. The best way to get started however, is to learn how to use tools such as built-in browser network and performance tools, to see what parts of the page load are taking a long time and need optimizing.

Optimizing JavaScript downloads
-------------------------------

The most performant, least blocking JavaScript you can use is JavaScript that you don't use at all. You should use as little JavaScript as possible. Some tips to bear in mind:

* **You don't always need a framework**: You might be familiar with using a JavaScript framework. If you are experienced and confident with using this framework, and like all of the tooling it provides, then it might be your go-to tool for building most projects. However, frameworks are JavaScript-heavy. If you are creating a fairly static experience with few JavaScript requirements, you probably don't need that framework. You might be able to implement what you need using a few lines of standard JavaScript.
* **Consider a simpler solution**: You might have a flashy, interesting solution to implement, but consider whether your users will appreciate it. Would they prefer something simpler?
* **Remove unused code:** This may sound obvious, but it is surprising how many developers forget to clean up unused functionality that was added during the development process. You need to be careful and deliberate about what is added and removed. All script gets parsed, whether it is used or not; therefore, a quick win to speed up downloads would be to get rid of any functionality not being used. Consider also that often you will only use a small amount of the functionality available in a framework. Is it possible to create a custom build of the framework that only contains the part that you need?
* **Consider built-in browser features**: It might be that you can use a feature the browser already has, rather than creating your own via JavaScript. For example:
    + Use built-in client-side form validation.
    + Use the browser's own `<video>` player.
    + Use CSS animations instead of a JavaScript animation library (see also Handling animations).

You should also split your JavaScript into multiple files representing critical and non-critical parts. JavaScript modules allow you to do this more efficiently than just using separate external JavaScript files.

Then you can optimize these smaller files. Minification reduces the number of characters in your file, thereby reducing the number of bytes or weight of your JavaScript. Gzipping compresses the file further and should be used even if you don't minify your code. Brotli is similar to Gzip, but generally outperforms Gzip compression.

You can split and optimize your code manually, but often a module bundler like Webpack will do a better job of this.

Handling parsing and execution
------------------------------

Before looking at the tips contained in this section, it is important to talk about *where* in the process of browser page rendering JavaScript is handled. When a web page is loaded:

1. The HTML is generally parsed first, in the order in which it appears on the page.
2. Whenever CSS is encountered, it is parsed to understand the styles that need to be applied to the page. During this time, linked assets such as images and web fonts start to be fetched.
3. Whenever JavaScript is encountered, the browser parses, evaluates, and runs it against the page.
4. Slightly later on, the browser works out how each HTML element should be styled, given the CSS applied to it.
5. The styled result is then painted to the screen.

**Note:** This is a very simplified account of what happens, but it does give you an idea.

The key step here is Step 3. By default, JavaScript parsing and execution are render-blocking. This means that the browser blocks the parsing of any HTML that appears after the JavaScript is encountered, until the script has been handled. As a result, styling and painting are blocked too. This means that you need to think carefully not only about what you are downloading, but also about when and how that code is being executed.

The next few sections provide useful techniques for optimizing the parsing and execution of your JavaScript.

Loading critical assets as soon as possible
-------------------------------------------

If a script is really important and you are concerned that it is affecting performance by not being loaded quickly enough, you can load it inside the `<head>` of the document:

```html
<head>
  ...
  <script src="main.js"></script>
  ...
</head>
```

This works OK, but is render-blocking. A better strategy is to use `rel="preload"` to create a preloader for critical JavaScript:

```html
<head>
  ...
  <!-- Preload a JavaScript file -->
  <link rel="preload" href="important-js.js" as="script" />
  <!-- Preload a JavaScript module -->
  <link rel="modulepreload" href="important-module.js" />
  ...
</head>
```

The preload `<link>` fetches the JavaScript as soon as possible, without blocking rendering. You can then use it wherever you want in your page:

```html
<!-- Include this wherever makes sense -->
<script src="important-js.js"></script>
```

or inside your script, in the case of a JavaScript module:

```js
import { function } from "important-module.js";
```

**Note:** Preloading does not guarantee that the script will be loaded by the time you include it, but it does mean that it will start being downloaded sooner. Render-blocking time will still be shortened, even if it is not completely removed.

Deferring execution of non-critical JavaScript
----------------------------------------------

On the other hand, you should aim to defer parsing and execution of non-critical JavaScript to later on, when it is needed. Loading it all up-front blocks rendering unnecessarily.

First of all, you can add the `async` attribute to your `<script>` elements:

```html
<head>
  ...
  <script async src="main.js"></script>
  ...
</head>
```

This causes the script to be fetched in parallel with the DOM parsing, so it will be ready at the same time and won't block rendering.

**Note:** There is another attribute, `defer`, which causes the script to be executed after the document has been parsed, but before firing the `DOMContentLoaded` event. This has a similar effect to `async`.

You could also just not load the JavaScript at all until an event occurs when it is needed. This could be done via DOM scripting, for example:

```js
const scriptElem = document.createElement("script");
scriptElem.src = "index.js";
scriptElem.addEventListener("load", () => {
  // Run a function contained within index.js once it has definitely loaded
  init();
});
document.head.append(scriptElem);
```

JavaScript modules can be dynamically loaded using the `import()` function:

```js
import("./modules/myModule.js").then((module) => {
  // Do something with the module
});
```

Breaking down long tasks
------------------------

When the browser runs your JavaScript, it will organize the script into tasks that are run sequentially, such as making fetch requests, driving user interactions and input through event handlers, running JavaScript-driven animation, and so on.

Most of this happens on the main thread, with exceptions including JavaScript that runs in Web Workers. The main thread can run only one task at a time.

When a single task takes longer than 50 ms to run, it is classified as a long task. If the user attempts to interact with the page or an important UI update is requested while a long task is running, their experience will be affected. An expected response or visual update will be delayed, resulting in the UI appearing sluggish or unresponsive.

To mitigate this issue, you need to break down long tasks into smaller tasks. This gives the browser more chances to perform vital user interaction handling or UI rendering updates — the browser can potentially do them between each smaller task, rather than only before or after the long task. In your JavaScript, you might do this by breaking your code into separate functions. This also makes sense for several other reasons, such as easier maintenance, debugging, and writing tests.

For example:

```js
function main() {
  a();
  b();
  c();
  d();
  e();
}
```

However, this kind of structure doesn't help with main thread blocking. Since all the five functions are being run inside one main function, the browser runs them all as a single long task.

To handle this, we tend to run a "yield" function periodically to get the code to *yield to the main thread*. This means that our code is split into multiple tasks, between the execution of which the browser is given the opportunity to handle high-priority tasks such as updating the UI. A common pattern for this function uses `setTimeout()` to postpone execution into a separate task:

```js
function yield() {
  return new Promise((resolve) => {
    setTimeout(resolve, 0);
  });
}
```

This can be used inside a task runner pattern like so, to yield to the main thread after each task has been run:

```js
async function main() {
  // Create an array of functions to run
  const tasks = [a, b, c, d, e];

  // Loop over the tasks
  while (tasks.length > 0) {
    // Shift the first task off the tasks array
    const task = tasks.shift();

    // Run the task
    task();

    // Yield to the main thread
    await yield();
  }
}
```

To improve this further, we can use `navigator.scheduling.isInputPending()` to run the `yield()` function only when the user is attempting to interact with the page:

```js
async function main() {
  // Create an array of functions to run
  const tasks = [a, b, c, d, e];

  while (tasks.length > 0) {
    // Yield to a pending user input
    if (navigator.scheduling.isInputPending()) {
      await yield();
    } else {
      // Shift the first task off the tasks array
      const task = tasks.shift();

      // Run the task
      task();
    }
  }
}
```

This allows you to avoid blocking the main thread when the user is actively interacting with the page, potentially providing a smoother user experience. However, by only yielding when necessary, we can continue running the current task when there are no user inputs to process. This also avoids tasks being placed at the back of the queue behind other non-essential browser-initiated tasks that were scheduled after the current one.

Handling JavaScript animations
------------------------------

Animations can improve perceived performance, making interfaces feel snappier and making users feel like progress is being made when they are waiting for a page to load (loading spinners, for example). However, larger animations and a higher number of animations will naturally require more processing power to handle, which can degrade performance.

The most obvious piece of animation advice is to use less animations — cut out any non-essential animations, or consider giving your users a preference they can set to turn off animations, for example if they are using a low-powered device or a mobile device with limited battery power.

For essential DOM animations, you are advised to use CSS animations where possible, rather than JavaScript animations (the Web Animations API provides a way to directly hook into CSS animations using JavaScript). Using the browser to directly perform DOM animations rather than manipulating inline styles using JavaScript is much faster and more efficient. See also CSS performance optimization > Handling animations.

For animations that can't be handled in JavaScript, for example, animating an HTML `<canvas>`, you are advised to use `Window.requestAnimationFrame()` rather than older options such as `setInterval()`. The `requestAnimationFrame()` method is specially designed for handling animation frames efficiently and consistently, for a smooth user experience. The basic pattern looks like this:

```js
function loop() {
  // Clear the canvas before drawing the next frame of the animation
  ctx.fillStyle = "rgb(0 0 0 / 25%)";
  ctx.fillRect(0, 0, width, height);

  // Draw objects on the canvas and update their positioning data
  // ready for the next frame
  for (const ball of balls) {
    ball.draw();
    ball.update();
  }

  // Call requestAnimationFrame to run the loop() function again
  // at the right time to keep the animation smooth
  requestAnimationFrame(loop);
}

// Call the loop() function once to set the animation running
loop();
```

You can find a nice introduction to canvas animations at Drawing graphics > Animations, and a more in-depth example at Object building practice. You can also find a full set of canvas tutorials at Canvas tutorial.

Optimizing event performance
----------------------------

Events can be expensive for the browser to track and handle, especially when you are running an event continuously. For example, you might be tracking the position of the mouse using the `mousemove` event to check whether it is still inside a certain area of the page:

```js
function handleMouseMove() {
  // Do stuff while mouse pointer is inside elem
}

elem.addEventListener("mousemove", handleMouseMove);
```

You might be running a `<canvas>` game in your page. While the mouse is inside the canvas, you will want to constantly check for mouse movement and cursor position and update the game state — including the score, the time, the position of all the sprites, collision detection information, etc. Once the game is over, you will no longer need to do all that, and in fact, it will be a waste of processing power to keeping listening for that event.

It is, therefore, a good idea to remove event listeners that are no longer needed. This can be done using `removeEventListener()`:

```js
elem.removeEventListener("mousemove", handleMouseMove);
```

Another tip is to use event delegation wherever possible. When you have some code to run in response to a user interacting with any one of a large number of child elements, you can set an event listener on their parent. Events fired on any child element will bubble up to their parent, so you don't need to set the event listener on each child individually. Less event listeners to keep track of means better performance.

See Event delegation for more details and a useful example.

Tips for writing more efficient code
------------------------------------

There are several general best practices that will make your code run more efficiently.

* **Reduce DOM manipulation**: Accessing and updating the DOM is computationally expensive, so you should minimize the amount that your JavaScript does, especially when performing constant DOM animation (see Handling JavaScript animations above).
* **Batch DOM changes**: For essential DOM changes, you should batch them into groups that get done together, rather than just firing off each individual change as it occurs. This can reduce the amount of work the browser is doing in real terms, but also improve perceived performance. It can make the UI look smoother to get several updates out of the way in one go, rather than constantly making small updates. A useful tip here is — when you have a large chunk of HTML to add to the page, build the entire fragment first (typically inside a `DocumentFragment`) and then append it all to the DOM in one go, rather than appending each item separately.
* **Simplify your HTML**: The simpler your DOM tree is, the faster it can be accessed and manipulated with JavaScript. Think carefully about what your UI needs, and remove unnecessary cruft.
* **Reduce the amount of looped code**: Loops are expensive, so reduce the amount of loop usage in your code wherever possible. In cases where loops are unavoidable:
    + Avoid running the full loop when it is unnecessary, using `break` or `continue` statements as appropriate. For example, if you are searching arrays for a specific name, you should break out of the loop once the name is found; there is no need to run further loop iterations:
     js
    ```js
    function processGroup(array) {
      const toFind = "Bob";
      for (let i = 0; i < array.length - 1; i++) {
        if (array[i] === toFind) {
          processMatchingArray(array);
          break;
        }
      }
    }

    ```
    + Do work that is only needed once outside the loop. This may sound a bit obvious, but it is easy to overlook. Take the following snippet, which fetches a JSON object containing data to be processed in some way. In this case the `fetch()` operation is being done on every iteration of the loop, which is a waste of computing power. Lines 3 and 4 could be moved outside the loop, so the network fetch is only being done once.
     js
    ```js
    async function returnResults(number) {
      for (let i = 0; i < number; i++) {
        const response = await fetch(`/results?number=${number}`);
        const results = await response.json();
        processResult(results[i]);
      }
    }

    ```
* **Run computation off the main thread**: Earlier on we talked about how JavaScript generally runs tasks on the main thread, and how long operations can block the main thread, potentially leading to bad UI performance. We also showed how to break long tasks up into smaller tasks, mitigating this problem. Another way to handle such problems is to move tasks off the main thread altogether. There are a few ways to achieve this:
    + Use asynchronous code: Asynchronous JavaScript is basically JavaScript that does not block the main thread. Asynchronous APIs tend to handle operations such as fetching resources from the network, accessing a file on the local file system, or opening a stream to a user's web cam. Because those operations could take a long time, it would be bad to just block the main thread while we wait for them to complete. Instead, the browser executes those functions, keeps the main thread running subsequent code, and those functions will return results once they are available *at some point in the future*. Modern asynchronous APIs are `Promise`-based, which is a JavaScript language feature designed for handling asynchronous operations. It is possible to write your own Promise-based functions if you have functionality that would benefit from being run asynchronously.
    + Run computation in web workers: Web Workers are a mechanism allowing you to open a separate thread to run a chunk of JavaScript in, so that it won't block the main thread. Workers do have some major restrictions, the biggest being that you can't do any DOM scripting inside a worker. You can do most other things, and workers can send and receive messages to and from the main thread. The main use case for workers is if you have a lot of computation to do, and you don't want it to block the main thread. Do that computation in a worker, wait for the result, and send it back to the main thread when it is ready.
    + **Use WebGPU**: WebGPU is a browser API that allows web developers to use the underlying system's GPU (Graphics Processing Unit) to carry out high-performance computations and draw complex images that can be rendered in the browser. It is fairly complex, but it can provide even better performance benefits than web workers.
See also
--------

* Optimize long tasks on web.dev (2022)
* Canvas tutorial
* Previous
* Overview: Performance
* Next


The "why" of web performance - Learn web development

The "why" of web performance
============================

* Overview: Performance
* Next

Web performance is all about making websites fast, including making slow processes *seem* fast. This article provides an introduction into why web performance is important to site visitors and for your business goals.

|  |  |
| --- | --- |
| Prerequisites: | Basic software installed, and basic knowledge of
 client-side web technologies.
  |
| Objective: |
 To gain basic familiarity of why web performance is important for good
 user experience.
  |

Web performance refers to how quickly site content **loads** and **renders** in a web browser, and how well it responds to user interaction. Bad performing sites are slow to display and slow to respond to input. Bad performing sites increase site abandonment. At its worst, bad performance causes content to be completely inaccessible. A good goal for web performance is for users to not notice performance. While an individual's perception of site performance is subjective, loading and rendering can be measured. Good performance may not be obvious to most site visitors, but most will immediately recognize a sluggish site. That is why we care.

Why care about performance?
---------------------------

Web performance — and its associated best practices—are vital for your website visitors to have a good experience. In a sense, web performance can be considered a subset of web accessibility. With performance as with accessibility, you consider what device a site visitor is using to access the site and the device connection speed.

As an example, consider the loading experience of CNN.com, which at the time of this writing had over 400 HTTP requests with a file size of over 22.6MB.

* Imagine loading this on a desktop computer connected to a fibre optic network. This would seem relatively fast, and the file size would be largely irrelevant.
* Imagine loading that same site using tethered mobile data on a nine-year-old iPad while commuting home on public transportation. The same site will be slow to load, possibly verging on unusable depending on cell coverage. You might give up before it finishes loading.
* Imagine loading that same site on a $35 Huawei device in a rural India with limited coverage or no coverage. The site will be very slow to load—if it loads at all—with blocking scripts possibly timing out, and adverse CPU impact causing browser crashes if it does load.

A 22.6 MB site could take up to 83 seconds to load on a 3G network, with `DOMContentLoaded` (meaning the site's base HTML structure) at 31.86 seconds.

And it isn't just the time taken to download that is a major problem. A lot of countries still have internet connections that bill per megabyte. Our example 22.6 MB CNN.com experience would cost about 11% of the average Indian's daily wage to download. From a mobile device in Northwest Africa, it might cost two days of an average salary. And if this site were loaded on a US carrier's international roaming plan? The costs would make anyone cry. (See how much your site costs to download.)

### Improve conversion rates

Reducing the download and render time of a site improves conversion rates and user retention.

A **conversion rate** is the rate at which site visitors perform a measured or desired action. For example, this might be making a purchase, reading an article, or subscribing to a newsletter. The action being measured as the conversion rate depends on the website's business goals.

Performance impacts conversion; improving web performance improves conversion. Site visitors expect a site to load in two seconds or less; sometimes even less on mobile (where it generally takes longer). These same site visitors begin abandoning slow sites at 3 seconds.

The speed at which a site loads is one factor. If the site is slow to react to user interaction, or appears janky, this causes site visitors to lose interest and trust.

Here's some real-world examples of performance improvements:

* Tokopedia reduced render time from 14s to 2s for 3G connections and saw a 19% increase in visitors, 35% increase in total sessions, 7% increase in new users, 17% increase in active users and 16% increase in sessions per user.
* Rebuilding Pinterest pages for performance resulted in a 40% decrease in wait time, a 15% increase in SEO traffic and a 15% increase in conversion rate to signup.

To build websites and applications people want to use; to attract and retain site visitors, you need to create an accessible site that provides a good user experience. Building websites requires HTML, CSS, and JavaScript, typically including binary file types such as images and video. The decisions you make and the tools you choose as you build your site can greatly affect the performance of the finished work.

Good performance is an asset. Bad performance is a liability. Site speed directly affects bounce rates, conversion, revenue, user satisfaction, and search engine ranking. Performant sites have been shown to increase visitor retention and user satisfaction. Slow content has been shown to lead to site abandonment, with some visitors leaving to never return. Reducing the amount of data that passes between the client and the server lowers the costs to all parties. Reducing HTML/CSS/JavaScript and media file sizes reduces both the time to load and a site's power consumption (see performance budgets).

Tracking performance is important. Multiple factors, including network speed and device capabilities affect performance. There is no single performance metric; and differing business objectives may mean different metrics are more relevant to the goals of the site or the organization that it supports. How the performance of your site is perceived is user experience!

Conclusion
----------

Web performance is important for accessibility and also for other website metrics that serve the goals of an organization or business. Good or bad website performance correlates powerfully to user experience, as well as the overall effectiveness of most sites. This is why you should care about web performance.

* Overview: Performance
* Next


The business case for web performance - Learn web development

The business case for web performance
=====================================

* Previous
* Overview: Performance
* Next

We've discussed the importance of web performance. You've learned what you need to do to optimize for web performance. But how do you convince your clients and/or management to prioritize and invest in performance? In this section, we discuss creating a clear business case to convince decision-makers to make the investment.

|  |  |
| --- | --- |
| Prerequisites: |
 Basic knowledge of
 client-side web technologies, and a basic understanding of
 web performance optimization.
  |
| Objective: |
 To gain confidence in working with clients and management to get them to
 make web performance a priority.
  |

Making performance a business priority
--------------------------------------

We've discussed how prioritizing performance can improve user experience and therefore revenue. We know that not prioritizing web performance can result in a loss of business revenue. This article discusses how certain business metrics directly relate to a user's web performance experience and how to apply service design to boost the user's experiences of web performance. It highlights the importance of understanding how cumulative experiences impact conversion and retention rates.

### Performance budgets

Setting a web performance budget can help you make sure the team stays on track in keeping the site and help prevent regressions. A performance budget is a set of limits that are set to specify limits, such as the maximum number of HTTP requests allowed, the maximum total size of all the assets combined, the minimum allowable FPS on a specific device, etc., that must be maintained. The budget can be applied to a single file, a file type, all files loaded on a page, a specific metric, or a threshold over a period of time. The budget reflects reachable goals; whether they are time, quantity, or rule-based.

Defining and promoting a budget helps performance proponents advocate for good user experience against competing interests, such as marketing, sales, or even other developers that may want to add videos, 3rd party scripts, or even frameworks. Performance budgets help developer teams protect optimal performance for users while enabling the business to tap into new markets and deliver custom experiences.

### Key Performance Indicators

Setting key performance indicators (KPI) as objectives can highlight performance objectives that are also business objectives. KPIs can be both a set of important business metrics in measuring the impact of user experience and performance on the business's top line, and a way of demonstrating the benefits of prioritizing performance. Here are some KPIs to consider:

**Conversion Rate**

The percent of your traffic that takes an intended action, such as completing a purchase or signing up for a newsletter. When a business site is slow, it can prevent users from completing their intended task. This can lead to low conversion rates.

**Time on Site**

The average time that your users in aggregate spend on your site. When a site performs slowly, users are more likely to abandon the site prematurely which can lead to low time on site metrics.

**Net Promotion Score**

The net promoter score (NPS) is a metric for assessing customer-loyalty for a company's brand, product, or service. Poor user performance experiences can equate to poor brand reputation.

Setting conversion rate, time on site, and/or net promotion scores as KPIs give financial and other business goal value to the web performance efforts, and get help boost buy-in, with metrics to prove the efforts worth.

* Previous
* Overview: Performance


What is web performance? - Learn web development

What is web performance?
========================

* Previous
* Overview: Performance
* Next

Web performance is all about making websites fast, including making slow processes *seem* fast. Does the site load quickly, allow the user to start interacting with it quickly, and offer reassuring feedback if something is taking time to load (e.g. a loading spinner)? Are scrolling and animations smooth? This article provides a brief introduction to objective, measurable web performance\*, looking at what technologies, techniques, and tools are involved in web optimization.

|  |  |
| --- | --- |
| Prerequisites: | Basic software installed, and basic knowledge of
 client-side web technologies.
  |
| Objective: | To gain basic familiarity of what is involved with web performance. |

*\* versus subjective, perceived performance, covered in the next article*

What is web performance?
------------------------

Web performance is the objective measurement and perceived user experience of a website or application. This includes the following major areas:

* **Reducing overall load time**: How long does it take the files required to render the website to download on to the user's computer? This tends to be affected by latency, how big your files are, how many files there are, and other factors besides. A general strategy is to make your files as small as possible, reduce the number of HTTP requests made as much as possible, and employ clever loading techniques (such as preload) to make files available sooner.
* **Making the site usable as soon as possible**: This basically means loading your website assets in a sensible order so that the user can start to actually use it really quickly. Any other assets can continue to load in the background while the user gets on with primary tasks, and sometimes we only load assets when they are actually needed (this is called lazy loading). The measurement of how long it takes the site to get to a usable start after it has started loading is called time to interactive.
* **Smoothness and interactivity**: Does the application feel reliable and pleasurable to use? Is the scrolling smooth? Are buttons clickable? Are pop-ups quick to open up, and do they animate smoothly as they do so? There are a lot of best practices to consider in making apps feel smooth, for example using CSS animations rather than JavaScript for animation, and minimizing the number of repaints the UI requires due to changes in the DOM.
* **Perceived performance**: How fast a website seems to the user has a greater impact on user experience than how fast the website actually is. How a user perceives your performance is as important, or perhaps more important, than any objective statistic, but it's subjective, and not as readily measurable. Perceived performance is user perspective, not a metric. Even if an operation is going to take a long time (because of latency or whatever), it is possible to keep the user engaged while they wait by showing a loading spinner, or a series of useful hints and tips (or jokes, or whatever else you think might be appropriate). Such an approach is much better than just showing nothing, which will make it feel like it is taking a lot longer and possibly lead to your users thinking it is broken and giving up.
* **Performance measurements**: Web performance involves measuring the actual and perceived speeds of an application, optimizing where possible, and then monitoring the performance, to ensure that what you've optimized stays optimized. This involves a number of metrics (measurable indicators that can indicate success or failure) and tools to measure those metrics, which we will discuss throughout this module.

To summarize, many features impact performance including latency, application size, the number of DOM nodes, the number of resource requests made, JavaScript performance, CPU load, and more. It is important to minimize the loading and response times, and add additional features to conceal latency by making the experience as available and interactive as possible, as soon as possible, while asynchronously loading in the longer tail parts of the experience.

**Note:** Web performance includes both objective measurements like time to load, frames per second, and time to interactive, and subjective experiences of how long it felt like it took the content to load.

How content is rendered
-----------------------

To effectively understand web performance, the issues behind it, and the major topic areas we mentioned above, you really should understand some specifics about how browsers work. This includes:

* **How the browser works**. When you request a URL and hit
 `Enter`
 /
 `Return`
 , the browser finds out where the server is that holds that website's files, establishes a connection to it, and requests the files. See Populating the page: how the browser works for a detailed overview.
* **Source order**. Your HTML index file's source order can significantly affect performance. The download of additional assets linked to from the index file is generally sequential, based on source order, but this can be manipulated and should definitely be optimized, realizing that some resources block additional downloads until their content is parsed and executed.
* **The critical path**. This is the process that the browser uses to construct the web document once the files have been downloaded from the server. The browser follows a well-defined set of steps, and optimizing the critical rendering path to prioritize the display of content that relates to the current user action will lead to significant improvements in content rendering time. See Critical rendering path for more information.
* The **document object model**. The document object model, or DOM, is a tree structure that represents the content and elements of your HTML as a tree of nodes. This includes all the HTML attributes and the relationships between the nodes. Extensive DOM manipulation after the pages has loaded (e.g., adding, deleting, or moving of nodes) can affect performance, so it is worth understanding how the DOM works, and how such issues can be mitigated. Find out more at Document Object Model.
* **Latency**. We mention this briefly earlier on, but in brief, latency is the time it takes for your website assets to travel from the server to a user's computer. There is overhead involved in establishing TCP and HTTP connections, and some unavoidable latency in pushing the request and response bytes back and forth across the network, but there are certain ways to reduce latency (e.g. reducing the number of HTTP request you make by downloading fewer files, using a CDN to make your site more universally performant across the world, and using HTTP/2 to serve files more efficiently from the server). You can read all about this topic at Understanding Latency.
Conclusion
----------

That's it for now; we hope our brief overview of the web performance topic helped you to get an idea of what it is all about, and made you excited to learn more. Next up we'll look at perceived performance, and how you can use some clever techniques to make some unavoidable performance hits appear less severe to the user, or disguise them completely.

* Previous
* Overview: Performance
* Next


Multimedia: video - Learn web development

Multimedia: video
=================

* Previous
* Overview: Performance
* Next

As we learned in the previous section, media, namely images and video, account for over 70% of the bytes downloaded for the average website. We have already taken a look at optimizing images. This article looks at optimizing video to improve web performance.

|  |  |
| --- | --- |
| Prerequisites: | Basic software installed, and basic knowledge of
 client-side web technologies.
  |
| Objective: |
 To learn about the various video formats, their impact on performance,
 and how to reduce video impact on overall page load time while serving
 the smallest video file size based on each browser's file type support.
  |

Why optimize your multimedia?
-----------------------------

For the average website, 25% of bandwidth comes from video. Optimizing video has the potential for very large bandwidth savings that translate into better website performance.

Optimizing video delivery
-------------------------

The sections below describe the following optimization techniques:

* compress all video
* optimize `<source>` order
* set autoplay
* remove audio from muted video
* optimize video preload
* consider streaming
### Compress all videos

Most video compression work compares adjacent frames within a video, with the intent of removing detail that is identical in both frames. Compress the video and export to multiple video formats, including WebM, MPEG-4/H.264, and Ogg/Theora.

Your video editing software probably has a feature to reduce file size. If not, there are online tools, such as FFmpeg (discussed in section below), that encode, decode, convert, and perform other optimization functions.

### Optimize `<source>` order

Order video source from smallest to largest. For example, given video compressions in three different formats at 10MB, 12MB, and 13MB, declare the smallest first and the largest last:

```html
<video width="400" height="300" controls="controls">
  <!-- WebM: 10 MB -->
  <source src="video.webm" type="video/webm" />
  <!-- MPEG-4/H.264: 12 MB -->
  <source src="video.mp4" type="video/mp4" />
  <!-- Ogg/Theora: 13 MB -->
  <source src="video.ogv" type="video/ogv" />
</video>
```

The browser downloads the first format it understands. The goal is to offer smaller versions ahead of larger versions. With the smallest version, make sure that the most compressed video still looks good. There are some compression algorithms that can make video look (bad) like an animated GIF. While a 128 Kb video may seem like it could provide a better user experience than a 10 MB download, a grainy GIF-like video may reflect poorly on the brand or project.

See CanIUse.com for current browser support of video and other media types.

### Video autoplay

To ensure that a looping background video autoplays, you must add several attributes to the video tag: `autoplay`, `muted`, and `playsinline`.

```html
<video
 autoplay=""
 loop=""
 muted
 playsinline=""
 src="backgroundvideo.mp4"></video>
```

While the `loop` and `autoplay` make sense for a looping and autoplaying video, the `muted` attribute is required for autoplay in mobile browsers.

`Playsinline` is required for mobile Safari, allowing videos to play without forcing fullscreen mode.

### Remove audio from muted hero videos

For hero-video or other video without audio, removing audio is smart.

```html
<video autoplay="" loop="" muted playsinline="" id="hero-video">
  <source src="banner\_video.webm" type='video/webm; codecs="vp8, vorbis"' />
  <source src="web\_banner.mp4" type="video/mp4" />
</video>
```

This hero-video code (above) is common to conference websites and corporate home pages. It includes a video that is autoplaying, looping, and muted. There are no controls, so there is no way to hear audio. The audio is often empty, but still present, and still using bandwidth. There is no reason to serve audio with video that is always muted. **Removing audio can save 20% of the bandwidth.**

Depending on your choice of software, you might be able to remove audio during export and compression. If not, a free utility called FFmpeg can do it for you. This is the FFmpeg command string to remove audio:

```bash
ffmpeg -i original.mp4 -an -c:v copy audioFreeVersion.mp4
```

### Video preload

The preload attribute has three available options: `auto`|`metadata`|`none`. The default setting is `metadata`. These settings control how much of a video file downloads with page load. You can save data by deferring download for less popular videos.

Setting `preload="none"` results in none of the video being downloaded until playback. It delays startup, but offers significant data savings for videos with a low probability of playback.

Offering more modest bandwidth savings, setting `preload="metadata"` may download up to 3% of the video on page load. This is a useful option for some small or moderately sized files.

Changing the setting to `auto` tells the browser to automatically download the entire video. Do this only when playback is very likely. Otherwise, it wastes a lot of bandwidth.

### Consider streaming

Video streaming allows the proper video size and bandwidth (based on network speed) to be delivered to the end user. Similar to responsive images, the correct size video is delivered to the browser, ensuring fast video startup, low buffering, and optimized playback.

Conclusion
----------

Optimizing video has the potential to significantly improve website performance. Video files are relatively large compared to other website files, and always worthy of attention. This article explains how to optimize website video through reducing file size, with (HTML) download settings, and with streaming.

* Previous
* Overview: Performance
* Next


Measuring performance - Learn web development

Measuring performance
=====================

* Previous
* Overview: Performance
* Next

Measuring performance provides an important metric to help you assess the success of your app, site, or web service.

For example, you can use performance metrics to determine how your app performs compared to a competitor or compare your app's performance across releases. Your metrics should be relevant to your users, site, and business goals. They should be collected, measured consistently, and analyzed in a format that non-technical stakeholders can consume and understand.

This article introduces tools you can use to access web performance metrics, which can be used to measure and optimize your site's performance.

|  |  |
| --- | --- |
| Prerequisites: | Basic software installed, and basic knowledge of
 client-side web technologies.
  |
| Objective: |
 To provide information about web performance metrics that you can
 collect through various web performance APIs and tools that you can
 use to visualize that data.
  |

Performance tools
-----------------

There are several different tools available to help you measure and improve performance. These can generally be classified into two categories:

* Tools that indicate or measure performance, such as PageSpeed Insights or the Firefox Network Monitor and Performance Monitor. These tools show you how fast or slow your website is loading. They also indicate areas that can be improved to optimize your web app.
* Performance APIs that you can use to build custom performance tools.
General performance reporting tools
-----------------------------------

Tools like PageSpeed Insights can provide quick performance measurements. You can enter a URL and get a performance report in seconds. The report contains scores indicating how your website performs for mobile and desktop. This is a good start for understanding what you are doing well and what could be improved.

At the time of writing, MDN's performance report summary looks similar to the following:

![A screenshot of PageSpeed Insights report for the Mozilla homepage.](/en-US/docs/Learn/Performance/Measuring_performance/pagespeed-insight-mozilla-homepage.png)

A performance report contains information about things like how long a user has to wait before *anything* is displayed on the page, how many bytes need to be downloaded to display a page, and much more. It also lets you know if the measured values are considered good or bad.

webpagetest.org is another example of a tool that automatically tests your site and returns valuable metrics.

You can try running your favorite website through these tools and see the scores.

Network monitor tools
---------------------

Modern browsers have tools available that you can use to run against loaded pages and determine how they are performing; most of them work similarly. For example, the Firefox Network Monitor returns detailed information on all the assets downloaded from the network, along with a waterfall time graph that shows how long each one took to download.

![Firefox network monitor showing a list of assets that has loaded as well as load time per asset](/en-US/docs/Learn/Performance/Measuring_performance/network-monitor.png)

You should also check out Chrome's Network Monitor documentation.

Performance monitor tools
-------------------------

You can also use browser performance tools such as the Firefox Performance Monitor to measure the performance of a web app or site's user interface as you perform different actions. This indicates the features that might slow down your web app or site.

![Developer tools performance panel showing the waterfall of recording #1.](/en-US/docs/Learn/Performance/Measuring_performance/perf-monitor.png)

See also Chrome's Performance tool documentation.

Performance APIs
----------------

When writing code for the Web, many Web APIs are available to create your own performance-measuring tools.

You can use the Navigation Timing API to measure client-side web performance, including the amount of time needed to unload the previous page, how long domain lookups take, the total time spent executing the window's load handler, and more. You can use the API for metrics related to all the navigation events in the diagram below.

![The various handlers that the navigation timing API can handle including Navigation timing API metrics Prompt for unload redirect unload App cache DNS TCP Request Response Processing onLoad navigationStart redirectStart redirectEnd fetchStart domainLookupEnd domainLookupStart connectStart (secureConnectionStart) connectEnd requestStart responseStart responseEnd unloadStart unloadEnd domLoading domInteractive domContentLoaded domComplete loadEventStart loadEventEnd](/en-US/docs/Learn/Performance/Measuring_performance/navigationtimingapi.jpg)

The Performance API, which provides access to performance-related information for the current page, includes several APIs including the Navigation Timing API, the User Timing API, and the Resource Timing API. These interfaces allow the accurate measurement of the time it takes for JavaScript tasks to complete.

The PerformanceEntry object is part of the *performance timeline*. A *performance entry* can be directly created by making a performance *`mark`* or *`measure`* (for example by calling the `mark()` method) at an explicit point in an application. Performance entries are also created in indirect ways, such as loading a resource like an image.

The PerformanceObserver API can be used to observe performance measurement events and to notify you of new performance entries as they are recorded in the browser's performance timeline.

While this article does not dive into using these APIs, it is helpful to know they exist. Refer to the Navigation and timings article for further examples of using performance Web APIs.

Conclusion
----------

This article briefly overviews some tools that can help you measure performance on a web app or site. In the following article, we'll see how you can optimize images on your site to improve its performance.

* Previous
* Overview: Performance
* Next


Web performance resources - Learn web development

Web performance resources
=========================

* Previous
* Overview: Performance

 There are many reasons why your website should perform as well as possible.
 Below is a quick review of best practices, tools, APIs with links to provide more information about each topic.

Best practices
--------------

* Start with learning the critical rendering path of the browser. Knowing this will help you understand how to improve the performance of the site.
* Using *resource hints* such as `rel=preconnect`, `rel=dns-prefetch`, `rel=prefetch`, `rel=preload`.
* Keep the size of JavaScript to a minimum. Only use as much JavaScript as needed for the current page.
* CSS performance factors
* Use HTTP/2 on your server (or CDN).
* Use a CDN for resources which can reduce load times significantly.
* Compress your resources using gzip, Brotli, and Zopfli.
* Image optimization (use CSS animation, or SVG if possible).
* Lazy loading parts of your application outside the viewport. If you do, have a backup plan for SEO (e.g., render full page for bot traffic); for example, by using the `loading` attribute on the `<img>` element
* It is also crucial to realize what is really important to your users. It might not be absolute timing, but user perception.
Quick Wins
----------

### CSS

Web performance is all about user experience and perceived performance. As we learned in the critical rendering path document, linking CSS with a traditional link tag with rel="stylesheet" is synchronous and blocks rendering. Optimize the rendering of your page by removing blocking CSS.

To load CSS asynchronously one can set the media type to print and then change to all once loaded. The following snippet includes an onload attribute, requiring JavaScript, so it is important to include a noscript tag with a traditional fallback.

```html
<link
 rel="stylesheet"
 href="/path/to/my.css"
 media="print"
 onload="this.media='all'" />
<noscript><link rel="stylesheet" href="/path/to/my.css" /></noscript>
```

The downside with this approach is the flash of unstyled text (FOUT.) The simplest way to address this is by inlining CSS that is required for any content that is rendered above the fold, or what you see in the browser viewport before scrolling. These styles will improve perceived performance as the CSS does not require a file request.

```html
<style>
 /\* Insert your CSS here \*/
</style>
```

### JavaScript

Avoid JavaScript blocking by using the async or defer attributes, or link JavaScript assets after the page's DOM elements. JavaScript only block rendering for elements that appear after the script tag in the DOM tree.

### Web Fonts

EOT and TTF formats are not compressed by default. Apply compression such as GZIP or Brotli for these file types. Use WOFF and WOFF2. These formats have compression built in.

Within @font-face use font-display: swap. By using font display swap the browser will not block rendering and will use the backup system fonts that are defined. Optimize font weight to match the web font as closely as possible.

#### Icon web fonts

If possible avoid icon web fonts and use compressed SVGs. To further optimize inline your SVG data within HTML markup to avoid HTTP requests.

Tools
-----

* Learn to use the Firefox Dev Tools to profile your site.
* PageSpeed Insights can analyze your page and give some general hints to improve performance.
* Lighthouse can give you a detailed breakdown of many aspects of your site including performance, SEO and accessibility.
* Test your page's speed using WebPageTest.org, where you can use different real device types and locations.
* Try the Chrome User Experience Report which quantifies real user metrics.
* Define a performance budget.
### APIs

* Gather user metrics using the boomerang library.
* Or directly gather with window.performance.timing
### Things not to do (bad practices)

* Download everything
* Use uncompressed media files
See also
--------

* https://github.com/filamentgroup/loadCSS


Perceived performance - Learn web development

Perceived performance
=====================

* Previous
* Overview: Performance
* Next

**Perceived performance** is a subjective measure of website performance, responsiveness, and reliability. In other words, how fast a website seems to the user. It is harder to quantify and measure than the actual speed of operation, but perhaps even more important.

This article provides a brief introduction to the factors that affect perceived performance, along with a number of tools for assessing and improving the perception.

|  |  |
| --- | --- |
| Prerequisites: | Basic software installed, and basic knowledge of
 client-side web technologies.
  |
| Objective: | To gain basic familiarity of user perception of web performance. |

Overview
--------

The perception of how quickly (and smoothly) pages load and respond to user interaction is even more important than the actual time required to fetch the resources. While you may not be able to physically make your site run faster, you may well be able to improve how fast it *feels* for your users.

A good general rule for improving perceived performance is that it is usually better to provide a quick response and regular status updates than make the user wait until an operation fully completes (before providing any information). For example, when loading a page it is better to display the text when it arrives rather than wait for all the images and other resources. Even though the content has not fully downloaded the user can see something is happening and they can start interacting with the content.

**Note:** Time appears to pass more quickly for users who are actively engaged, distracted, or entertained, than for those who are waiting passively for something to happen. Where possible, actively engage and inform users who are waiting for a task to complete.

Similarly, it is better to display a "loading animation" as soon as a user clicks a link to perform a long-running operation. While this doesn't change the time taken to complete the operation, the site feels more responsive, and the user knows that it is working on something useful.

Performance metrics
-------------------

There is no single metric or test that can be run on a site to evaluate how a user "feels". However, there are a number of metrics that can be "helpful indicators":

First paint

The time to start of first paint operation. Note that this change may not be visible; it can be a simple background color update or something even less noticeable.

First Contentful Paint (FCP)

The time until first significant rendering (e.g. of text, foreground or background image, canvas or SVG, etc.). Note that this content is not necessarily useful or meaningful.

First Meaningful Paint (FMP)

The time at which useful content is rendered to the screen.

Largest Contentful Paint (LCP)

The render time of the largest content element visible in the viewport.

Speed index

Measures the average time for pixels on the visible screen to be painted.

Time to interactive

Time until the UI is available for user interaction (i.e. the last long task of the load process finishes).

Improving performance
---------------------

Here are a few tips and tricks to help improve perceived performance:

### Minimize initial load

To improve perceived performance, minimize the original page load. In other words, download the content the user is going to interact with immediately first, and download the rest after "in the background". The total amount of content downloaded may actually increase, but the user only *waits* on a very small amount, so the download feels faster.

Separate interactive functionality from content, and load text, styles, and images visible at initial load. Delay, or lazy load, images or scripts that aren't used or visible on the initial page load. Additionally, you should optimize the assets you do load. Images and video should be served in the most optimal format, compressed, and in the correct size.

### Prevent jumping content and other reflows

Images or other assets causing content to be pushed down or jump to a different location, like the loading of third party advertisements, can make the page feel like it is still loading and is bad for perceived performance. Content reflowing is especially bad for user experience when not initiated by user interaction. If some assets are going to be slower to load than others, with elements loading after other content has already been painted to the screen, plan ahead and leave space in the layout for them so that content doesn't jump or resize, especially after the site has become interactive.

### Avoid font file delays

Font choice is important. Selecting an appropriate font can greatly improve the user experience. From a perceived performance point of view, "suboptimal fonts importing" can result in flicker as text is styled or when falling back to other fonts.

Make fallback fonts the same size and weight so that when fonts load the page change is less noticeable.

### Interactive elements are interactive

Make sure visible interactive elements are always interactive and responsive. If input elements are visible, the user should be able to interact with them without a lag. Users feel that something is laggy when they take more than 50ms to react. They feel that a page is behaving poorly when content repaints slower than 16.67ms (or 60 frames per second) or repaints at uneven intervals.

Make things like type-ahead a progressive enhancement: use CSS to display input modal, JS to add autocomplete as it is available

### Make task initiators appear more interactive

Making a content request on `keydown` rather than waiting for `keyup` can reduce the perceived load time of the content by 200ms. Adding an interesting but unobtrusive 200ms animation to that `keyup` event can reduce another 200ms of the perceived load. You're not saving 400ms of time, but the user doesn't feel like they're waiting for content until, well, until they're waiting for content.

Conclusion
----------

By reducing the time that a user has to wait for *useful* content, and keeping the site responsive and engaging, the users will feel like the site performs better — even the actual time to load resources stays the same.

* Previous
* Overview: Performance
* Next


Multimedia: Images - Learn web development

Multimedia: Images
==================

* Previous
* Overview: Performance
* Next

Media, namely images and video, account for over 70% of the bytes downloaded for the average website. In terms of download performance, eliminating media, and reducing file size is the low-hanging fruit. This article looks at optimizing images and video to improve web performance.

|  |  |
| --- | --- |
| Prerequisites: | Basic software installed, and basic knowledge of
 client-side web technologies.
  |
| Objective: |
 To learn about the various image formats, their impact on performance,
 and how to reduce the impact of images on overall page load time.
  |

**Note:** This is a high-level introduction to optimizing multimedia delivery on the web, covering general principles and techniques. For a more in-depth guide, see https://web.dev/learn/images.

Why optimize your multimedia?
-----------------------------

For the average website, 51% of its bandwidth comes from imagery, followed by video at 25%, so it's safe to say it's important to address and optimize your multimedia content.

You need to be considerate of data usage. Many people are on capped data plans or even pay-as-you-go where they are literally paying by the megabyte. This isn't an emerging market problem either. As of 2018, 24% of the United Kingdom still use pay-as-you-go.

You also need to be considerate of memory as many mobile devices have limited RAM. It's important to remember that when images are downloaded, they need to be stored in memory.

Optimizing image delivery
-------------------------

Despite being the largest consumer of bandwidth, the impact of image downloading on perceived performance is far lower than many expect (primarily because the page text content is downloaded immediately and users can see the images being rendered as they arrive). However, for a good user experience it's still important that a visitor can see them as soon as possible.

### Loading strategy

One of the biggest improvements to most websites is lazy-loading images beneath the fold, rather than downloading them all on initial page load regardless of whether a visitor scrolls to see them or not. Many JavaScript libraries can implement this for you, such as lazysizes, and browser vendors are working on a native `lazyload` attribute that is currently in the experimental phase.

Beyond loading a subset of images, you should look into the format of the images themselves:

* Are you loading the most optimal file formats?
* Have you compressed the images well?
* Are you loading the correct sizes?

#### The most optimal format

The optimal file format typically depends on the character of the image.

**Note:** For general information on image types see the Image file type and format guide

The SVG format is more appropriate for images that have few colors and that are not photo-realistic. This requires the source to be available as in a vector graphic format. Should such an image only exist as a bitmap, then PNG would be the fallback format to choose. Examples of these types of motifs are logos, illustrations, charts, or icons (note: SVGs are far better than icon fonts!). Both formats support transparency.

PNGs can be saved with three different output combinations:

* 24-bit color + 8-bit transparency — offer full-color accuracy and smooth transparency at the expense of size. You probably want to avoid this combination in favor of WebP (see below).
* 8-bit color + 8-bit transparency — offer no more than 255 colors but maintain smooth transparencies. The size is not too big. Those are the PNGs you would probably want.
* 8-bit color + 1-bit transparency — offer no more than 255 colors and just offer no or full transparency per pixel which makes the transparency borders appear hard and jagged. The size is small but the price is visual fidelity.

A good online tool for optimizing SVGs is SVGOMG. For PNGs there is ImageOptim online or Squoosh.

With photographic motifs that do not feature transparency, there is a much wider range of formats to choose from. If you want to play it safe, then you would go for well-compressed **Progressive JPEGs**. Progressive JPEGs, in contrast to normal JPEGs, render progressively (hence the name), meaning the user sees a low-resolution version that gains clarity as the image downloads, rather than the image loading at full resolution top-to-bottom or even only rendering once completely downloaded. A good compressor for these would be MozJPEG, e.g. available to use in the online image optimization tool Squoosh. A quality setting of 75% should yield decent results.

Other formats improve on JPEG's capabilities regarding compression, but are not available on every browser:

* WebP — Excellent choice for both images and animated images. WebP offers much better compression than PNG or JPEG with support for higher color depths, animated frames, transparency, etc. (but not progressive display.). Supported by all major browsers except Safari 14 on macOS desktop Big Sur or earlier.

**Note:** Despite Apple announcing support for WebP in Safari 14, Safari versions earlier than 16.0 don't display `.webp` images successfully on macOS desktop versions earlier than 11/Big Sur. Safari for iOS 14 *does* display `.webp` images successfully.
* AVIF — Good choice for both images and animated images due to high performance and royalty-free image format (even more efficient than WebP, but not as widely supported). It is now supported on Chrome, Edge, Opera, and Firefox. See also an online tool to convert previous image formats to AVIF.
* **JPEG2000** — once to be the successor to JPEG but only supported in Safari. Doesn't support progressive display either.

Given the narrow support for JPEG-XR and JPEG2000, and also taking decode costs into the equation, the only serious contender for JPEG is WebP. Which is why you could offer your images in that flavor too. This can be done via the `<picture>` element with the help of a `<source>` element equipped with a type attribute.

If all of this sounds a bit complicated or feels like too much work for your team then there are also online services that you can use as image CDNs that will automate the serving of the correct image format on the fly, according to the type of device or browser requesting the image. The biggest ones are Cloudinary and Image Engine.

Finally, should you want to include animated images on your page, then know that Safari allows the use of video files within `<img>` and `<picture>` elements. These also allow you to add in an **Animated WebP** for all other modern browsers.

```html
<picture>
  <source type="video/mp4" src="giphy.mp4" />
  <source type="image/webp" src="giphy.webp" />
  <img src="giphy.gif" alt="A GIF animation" />
</picture>
```

#### Serving the optimal size

In image delivery the "one size fits all" approach will not yield the best results, meaning that for smaller screens you would want to serve images with smaller resolution and vice versa for larger screens. On top of that, you'd also want to serve higher resolution images to those devices that boast a high DPI screen (e.g. "Retina"). So apart from creating plenty of intermediate image variants you also need a way to serve the right file to the right browser. That's where you would need to upgrade your `<picture>` and `<source>` elements with media and/or sizes attributes. A detailed article on how to combine all of these attributes can be found here.

Two interesting effects to keep in mind regarding high dpi screens is that:

* with a high DPI screen, humans will spot compression artifacts a lot later, meaning that for images meant for these screens you can crank up compression beyond usual.
* Only a very few people can spot an increase in resolution beyond 2× DPI, which means you don't need to serve images resolving higher than 2×.

#### Controlling the priority (and ordering) of downloading images

Getting the most important images in front of visitors sooner than the less important can deliver improved perceived performance.

The first thing to check is that your content images use `<img>` or `<picture>` elements and your background images are defined in CSS with `background-image` — images referenced in `<img>` elements are assigned a higher loading priority than background images.

Secondly, with the adoption of Priority Hints, you can control the priority further by adding a `fetchPriority` attribute to your image tags. An example use case for priority hints on images are carousels where the first image is a higher priority than the subsequent images.

### Rendering strategy: preventing jank when loading images

As images are loaded asynchronously and continue to load after the first paint, if their dimensions aren't defined before load, they can cause reflows to the page content. For example, when text gets pushed down the page by images loading. For this reason, it's critical that you set `width` and `height` attributes so that the browser can reserve space for them in the layout.

When the `width` and `height` attributes of an image are included on an HTML `<img>` element, the aspect ratio of the image can be calculated by the browser prior to the image being loaded. This aspect ratio is used to reserve the space needed to display the image, reducing or even preventing a layout shift when the image is downloaded and painted to the screen. Reducing layout shift is a major component of good user experience and web performance.

Browsers begin rendering content as HTML is parsed, often before all assets, including images, are downloaded. Including dimensions enable browsers to reserve a correctly-sized placeholder box for each image to appear in when the images are loaded when first rendering the page.

![Two screenshots the first without an image but with space reserved, the second showing the image loaded into the reserved space.](/en-US/docs/Learn/Performance/Multimedia/ar-guide.jpg)

Without the `width` and `height` attributes, no placeholder space is created, creating a noticeable jank, or layout shift, in the page when the image loads after the page is rendered. Page reflow and repaints are performance and usability issues.

In responsive designs, when a container is narrower than an image, the following CSS is generally used to keep images from breaking out of their containers:

```css
img {
  max-width: 100%;
  height: auto;
}
```

While useful for responsive layouts, this causes jank when width and height information are not included, as if no height information is present when the `<img>` element is parsed but before the image has loaded, this CSS effectively has set the height to 0. When the image loads after the page has been initially rendered to the screen, the page reflows and repaints creating a layout shift as it creates space for the newly determined height.

Browsers have a mechanism for sizing images before the actual image is loaded. When an `<img>`, `<video>`, or `<input type="button">` element has `width` and `height` attributes set on it, its aspect ratio is calculated before load time, and is available to the browser, using the dimensions provided.

The aspect ratio is then used to calculate the height and therefore the correct size is applied to the `<img>` element, meaning that the aforementioned jank will not occur, or be minimal if the listed dimensions are not fully accurate, when the image loads.

The aspect ratio is used to reserve space only on the image load. Once the image has loaded, the intrinsic aspect ratio of the loaded image, rather than the aspect ratio from the attributes, is used. This ensures that it displays at the correct aspect ratio even if the attribute dimensions are not accurate.

While developer best practices from the last decade may have recommended omitting the `width` and `height` attributes of an image on an HTML `<img>`, due to aspect ratio mapping, including these two attributes is considered a developer best practice.

For any background images, it's important you set a `background-color` value so any content overlaid is still readable before the image has downloaded.

Conclusion
----------

In this section, we took a look at image optimization. You now have a general understanding of how to optimize half of the average website's average bandwidth total. This is just one of the types of media consuming users' bandwidth and slowing down page load. Let's take a look at video optimization, tackling the next 20% of bandwidth consumption.

* Previous
* Overview: Performance
* Next


HTML performance optimization - Learn web development

HTML performance optimization
=============================

* Previous
* Overview: Performance
* Next

HTML is by default fast and accessible. It is our job, as developers, to ensure that we preserve these two properties when creating or editing HTML code. Complications can occur when, for example, the file size of a `<video>` embed is too large or when JavaScript parsing blocks the rendering of critical page elements. This article walks you through the key HTML performance features that can drastically improve the quality of your web page.

|  |  |
| --- | --- |
| Prerequisites: | Basic software installed, and basic knowledge of
 client-side web technologies.
  |
| Objective: |
 To learn about the impact of HTML on website performance
 and how to optimize your HTML to improve performance.
  |

To optimize or not to optimize
------------------------------

The first question you should answer before starting to optimize your HTML is "what do I need to optimize?". Some of the tips and techniques discussed below are good practices that will benefit just about any web project, whereas some are only needed in certain situations. Trying to apply all these techniques everywhere is probably unnecessary, and may be a waste of your time. You should figure out what performance optimizations are actually needed in each project.

To do this, you need to measure the performance of your site. As this link shows, there are several different ways to measure performance, some involving sophisticated performance APIs. The best way to get started, however, is to learn how to use tools such as built-in browser network and performance tools, to examine the parts of the page that are taking a long time to load and need optimizing.

Key HTML performance issues
---------------------------

HTML is simple in terms of performance — it is mostly text, which is small in size, and therefore, mostly quick to download and render. The key issues that can impact the performance of a web page include:

* Size of the image and video files: It is important to consider how to handle the content of replaced elements such as `<img>` and `<video>`. Image and video files are large and can add significantly to the weight of the page. Therefore, it is important to minimize the amount of bytes that get downloaded on a user's device (for example, serve smaller images for mobile). You also need to consider improving the perceived performance by loading images and videos on a page only when they are needed.
* Delivery of embedded content: This is usually the content embedded in `<iframe>` elements. Loading content into `<iframe>`s can impact performance significantly, so it should be considered carefully.
* Order of resource loading: To maximize the perceived and actual performance, the HTML should be loaded first, in the order in which it appears on the page. You can then use various features to influence the order of resource loading for better performance. For example, you can preload critical CSS and fonts early, but defer non-critical JavaScript until later on.

**Note:** There is an argument to be made for simplifying your HTML structure and minifying your source code, so that rendering and downloads are faster. However, HTML file size is negligible compared to images and videos, and browser rendering is very fast these days. If your HTML source is so large and complex that it is creating rendering and download performance hits, you probably have bigger problems, and should aim to simplify it and split the content up.

Responsive handling of replaced elements
----------------------------------------

Responsive design has revolutionized the way that web content layout is handled across different devices. One key advantage that it enables is dynamic switching of layouts optimized for different screen sizes, for example a wide screen layout versus a narrow (mobile) screen layout. It can also handle dynamic switching of content based on other device attributes, such as resolution or preference for light or dark color scheme.

The so-called "mobile first" technique can ensure that the default layout is for small-screen devices, so mobiles can just download images suitable for their screens, and don't need to take the performance hit of downloading larger desktop images. However, since this is controlled using media queries in your CSS, it can only positively affect performance of images loaded in CSS.

In the sections below, we'll summarize how to implement responsive replaced elements. You can find a lot more detail about these implementations in the Video and audio content and Responsive images guides.

### Providing different image resolutions via srcset

To provide different resolution versions of the same image depending on the device's resolution and viewport size, you can use the `srcset` and `sizes` attributes.

This example provides different size images for different screen widths:

```html
<img
 srcset="480w.jpg 480w, 800w.jpg 800w"
 sizes="(max-width: 600px) 480px,
 800px"
 src="800w.jpg"
 alt="Family portrait" />
```

`srcset` provides the intrinsic size of the source images along with their filenames, and `sizes` provides media queries alongside image slot widths that need to be filled in each case. The browser then decides which images makes sense to load for each slot. As an example, if the screen width is `600px` or less, then `max-width: 600px` is true, and therefore, the slot to fill is said to be `480px`. In this case, the browser will likely choose to load the 480w.jpg file (480px-wide image). This helps with performance because browsers don't load larger images than they need.

This example provides different resolution images for different screen resolutions:

```html
<img
 srcset="320w.jpg, 480w.jpg 1.5x, 640w.jpg 2x"
 src="640w.jpg"
 alt="Family portrait" />
```

`1.5x`, `2x`, etc. are relative resolution indicators. If the image is styled to be 320px-wide (for example with `width: 320px` in CSS), the browser will load `320w.jpg` if the device is low resolution (one device pixel per CSS pixel), or `640x.jpg` if the device is high resolution (two device pixels per CSS pixel or more).

In both cases, the `src` attribute provides a default image to load if the browser does not support `src`/`srcset`.

### Providing different sources for images and videos

The `<picture>` element builds on the traditional `<img>` element, allowing you to provide multiple different sources for different situations. For example if the layout is wide, you will probably want a wide image, and if it is narrow, you will want a narrower image that still works in that context.

Of course, this also works to provide a smaller download of information on mobile devices, helping with performance.

An example is as follows:

```html
<picture>
  <source media="(max-width: 799px)" srcset="narrow-banner-480w.jpg" />
  <source media="(min-width: 800px)" srcset="wide-banner-800w.jpg" />
  <img src="large-banner-800w.jpg" alt="Dense forest scene" />
</picture>
```

The `<source>` elements contain media queries inside `media` attributes. If a media query returns true, the image referenced in its `<source>` element's `srcset` attribute is loaded. In the above example, if the viewport width is `799px` or less, the `narrow-banner-480w.jpg` image is loaded. Also note how the `<picture>` element includes an `<img>` element, which provides a default image to load in the case of browsers that don't support `<picture>`.

Note the use of the `srcset` attribute in this example. As shown in the previous section, you can provide different resolutions for each image source.

`<video>` elements work in a similar way, in terms of providing different sources:

```html
<video controls>
  <source src="video/smaller.mp4" type="video/mp4" />
  <source src="video/smaller.webm" type="video/webm" />
  <source src="video/larger.mp4" type="video/mp4" media="(min-width: 800px)" />
  <source
 src="video/larger.webm"
 type="video/webm"
 media="(min-width: 800px)" />

  <!-- fallback for browsers that don't support video element -->
  <a href="video/larger.mp4">download video</a>
</video>
```

There are, however, some key differences between providing sources for images and videos:

* In the above example, we are using `src` rather than `srcset`; you can't specify different resolutions for videos via `srcset`.
* Instead, you specify different resolutions inside the different `<source>` elements.
* Note how we are also specifying different video formats inside different `<source>` elements, with each format being identified via its MIME type inside the `type` attribute. Browsers will load the first one they come across that they support, where the media query test returns true.
### Lazy loading images

A very useful technique for improving performance is **lazy loading**. This refers to the practice of not loading all images immediately when the HTML is rendered, but instead only loading them when they are actually visible to the user in the viewport (or imminently visible). This means that the immediately visible/usable content is ready to use more quickly, whereas subsequent content only has its images rendered when scrolled to, and the browser won't waste bandwidth loading images that the user will never see.

Lazy loading has historically been handled using JavaScript, but browsers now have a `loading` attribute available that can instruct the browser to lazy load images automatically:

```html
<img src="800w.jpg" alt="Family portrait" loading="lazy" />
```

See Browser-level image lazy loading for the web on web.dev for detailed information.

You can also lazy load video content by using the `preload` attribute. For example:

```html
<video controls preload="none" poster="poster.jpg">
  <source src="video.webm" type="video/webm" />
  <source src="video.mp4" type="video/mp4" />
</video>
```

Giving `preload` a value of `none` tells the browser to not preload any of the video data before the user decides to play it, which is obviously good for performance. Instead, it will just show the image indicated by the `poster` attribute. Different browsers have different default video loading behavior, so it is good to be explicit.

See Lazy loading video on web.dev for detailed information.

Handling embedded content
-------------------------

It is very common for content to be embedded in web pages from other sources. This is most commonly done when displaying advertising on a site to generate revenue — the ads are usually generated by a third-party company of some kind and embedded onto your page. Other uses might include:

* Displaying shared content that a user might need across multiple pages, such as a shopping cart or profile information.
* Displaying third-party content related to the organization's main site, such as a social media posts feed.

Embedding content is most commonly done using `<iframe>` elements, although other less commonly used embedding elements do exist, such as `<object>` and `<embed>`. We'll concentrate on `<iframe>`s in this section.

The most important and key piece of advice for using `<iframe>`s is: "Don't use embedded `<iframe>`s unless you absolutely have to". If you are creating a page with multiple different panes of information on it, it might sound organizationally sensible to break those up into separate pages and load them into different `<iframe>`s. However, this has a number of problems associated with it in terms of performance and otherwise:

* Loading the content into an `<iframe>` is much more expensive than loading the content as part of the same direct page — not only does it require extra HTTP requests to load the content, but the browser also needs to create a separate page instance for each one. Each one is effectively a separate web page instance embedded in the top-level web page.
* Following on from the previous point, you'll also need to handle any CSS styling or JavaScript manipulation separately for each different `<iframe>` (unless the embedded pages are from the same origin), which becomes much more complex. You can't target embedded content with CSS and JavaScript applied to the top-level page, or vice versa. This is a sensible security measure that is fundamental to the web. Imagine all the problems you might run into if third-party embedded content could arbitrarily run scripts against any page it was embedded in!
* Each `<iframe>` would also need to load any shared data and media files separately — you can't share cached assets across different page embeds (again, unless the embedded pages are from the same origin). This can lead to a page using much more bandwidth than you might expect.

It is advisable to put the content into a single page. If you want to pull in new content dynamically as the page changes, it is still better for performance to load it into the same page rather than putting it into an `<iframe>`. You might grab the new data using the `fetch()` method, for example, and then inject it into the page using some DOM scripting. See Fetching data from the server and Manipulating documents for more information.

**Note:** If you control the content and it is relatively simple, you could consider using base-64 encoded content in the `src` attribute to populate the `<iframe>`, or even insert raw HTML into the `srcdoc` attribute (See Iframe Performance Part 2: The Good News for more information).

If you must use `<iframe>`s, then use them sparingly.

#### Lazy loading iframes

In the same way as `<img>` elements, you can also use the `loading` attribute to instruct the browser to lazy-load `<iframe>` content that is initially offscreen, thereby improving performance:

```html
<iframe src="https://example.com" loading="lazy" width="600" height="400">
</iframe>
```

See It's time to lazy-load offscreen iframes! for more information.

Handling resource loading order
-------------------------------

Ordering of resource loading is important for maximizing perceived and actual performance. When a web page is loaded:

1. The HTML is generally parsed first, in the order in which it appears on the page.
2. Any found CSS is parsed to understand the styles that need to be applied to the page. During this time, linked assets such as images and web fonts start to be fetched.
3. Any found JavaScript is parsed, evaluated, and run against the page. By default, this blocks parsing of the HTML that appears after the `<script>` elements where the JavaScript is encountered.
4. Slightly later on, the browser works out how each HTML element should be styled, given the CSS applied to it.
5. The styled result is then painted to the screen.

**Note:** This is a very simplified account of what happens, but it does give you an idea.

Various HTML features allow you to modify how resource loading happens to improve performance. We'll explore some of these now.

### Handling JavaScript loading

Parsing and executing JavaScript blocks the parsing of subsequent DOM content. This increases the time until that content is rendered and usable by the users of the page. A small script won't make much difference, but consider that modern web applications tend to be very JavaScript-heavy.

Another side effect of the default JavaScript parsing behavior is that, if the script being rendered relies on DOM content that appears later on in the page, you'll get errors.

For example, imagine a simple paragraph on a page:

```html
<p>My paragraph</p>
```

Now imagine a JavaScript file that contains the following code:

```js
const pElem = document.querySelector("p");

pElem.addEventListener("click", () => {
  alert("You clicked the paragraph");
});
```

We can apply this script to the page by referring to it in a `<script>` element like this:

```html
<script src="index.js"></script>
```

If we put this `<script>` element before the `<p>` element in the source order (for example, in the `<head>` element), the page will throw an error (Chrome for example reports "Uncaught TypeError: Cannot read properties of null (reading 'addEventListener')" to the console). This occurs because the script relies on the `<p>` element to work, but at the point the script is parsed, the `<p>` element does not exist on the page. It has not yet been rendered.

You can fix the above issue by putting the `<script>` element after the `<p>` element (for example at the end of the document body), or by running the code inside a suitable event handler (for example run it on the `DOMContentLoaded`, which fires when the DOM has been completely parsed).

However, this doesn't solve the problem of waiting for the script to load. Better performance can be achieved by adding the `async` attribute to the `<script>` element:

```html
<script async src="index.js"></script>
```

This causes the script to be fetched in parallel with the DOM parsing, so it is ready at the same time, and won't block rendering, thereby improving performance.

**Note:** There is another attribute, `defer`, which causes the script to be executed after the document has been parsed, but before firing `DOMContentLoaded`. This has a similar effect to `async`.

Another JavaScript load handling tip is to split your script up into code modules and load each part when required, instead of putting all your code into one giant script and loading it all at the beginning. This is done using JavaScript modules. Read the linked article for a detailed guide.

### Preloading content with rel="preload"

The fetching of other resources (such as images, videos, or font files) linked to from your HTML, CSS, and JavaScript can also cause performance problems, blocking your code from executing and slowing down the experience. One way to mitigate such problems is to use `rel="preload"` to turn `<link>` elements into preloaders. For example:

```html
<link rel="preload" href="sintel-short.mp4" as="video" type="video/mp4" />
```

Upon coming across a `rel="preload"` link, the browser will fetch the referenced resource as soon as possible and make it available in the browser cache so that it will be ready for use sooner when it is referenced in subsequent code. It is useful to preload high-priority resources that the user will encounter early on in a page so that the experience is as smooth as possible.

See the following articles for detailed information on using `rel="preload"`:

* `rel="preload"`
* Preload critical assets to improve loading speed on web.dev (2020)

**Note:** You can use `rel="preload"` to preload CSS and JavaScript files as well.

**Note:** There are other `rel` values that are also designed to speed up various aspects of page loading: `dns-prefetch`, `preconnect`, `modulepreload`, `prefetch`, and `prerender`. Go to the linked page and find out what they do.

* Previous
* Overview: Performance
* Next
See also
--------

* Fetching data from the server
* Manipulating documents