Populating the page: how browsers work - Web performance

Populating the page: how browsers work
======================================

Users want web experiences with content that is fast to load and smooth to interact with. Therefore, a developer should strive to achieve these two goals.

To understand how to improve performance and perceived performance, it helps to understand how the browser works.

Overview
--------

Fast sites provide better user experiences. Users want and expect web experiences with content that is fast to load and smooth to interact with.

Two major issues in web performance are issues having to do with latency and issues having to do with the fact that for the most part, browsers are single-threaded.

Latency is the biggest threat to our ability to ensure a fast-loading page. It is the developers' goal to make the site load as fast as possible — or at least *appear* to load super fast — so the user gets the requested information as quickly as possible. Network latency is the time it takes to transmit bytes over the air to computers. Web performance is what we have to do to make the page load as quickly as possible.

For the most part, browsers are considered single-threaded. That is, they execute a task from beginning to end before taking up another task. For smooth interactions, the developer's goal is to ensure performant site interactions, from smooth scrolling to being responsive to touch. Render time is key, ensuring the main thread can complete all the work we throw at it and still always be available to handle user interactions. Web performance can be improved by understanding the single-threaded nature of the browser and minimizing the main thread's responsibilities, where possible and appropriate, to ensure rendering is smooth and responses to interactions are immediate.

Navigation
----------

*Navigation* is the first step in loading a web page. It occurs whenever a user requests a page by entering a URL into the address bar, clicking a link, submitting a form, as well as other actions.

One of the goals of web performance is to minimize the amount of time navigation takes to complete. In ideal conditions, this usually doesn't take too long, but latency and bandwidth are foes that can cause delays.

### DNS lookup

The first step of navigating to a web page is finding where the assets for that page are located. If you navigate to `https://example.com`, the HTML page is located on the server with IP address of `93.184.216.34`. If you've never visited this site, a DNS lookup must happen.

Your browser requests a DNS lookup, which is eventually fielded by a name server, which in turn responds with an IP address. After this initial request, the IP will likely be cached for a time, which speeds up subsequent requests by retrieving the IP address from the cache instead of contacting a name server again.

DNS lookups usually only need to be done once per hostname for a page load. However, DNS lookups must be done for each unique hostname the requested page references. If your fonts, images, scripts, ads, and metrics all have different hostnames, a DNS lookup will have to be made for each one.

![Mobile requests go first to the cell tower, then to a central phone company computer before being sent to the internet](/en-US/docs/Web/Performance/How_browsers_work/latency.jpg)

This can be problematic for performance, particularly on mobile networks. When a user is on a mobile network, each DNS lookup has to go from the phone to the cell tower to reach an authoritative DNS server. The distance between a phone, a cell tower, and the name server can add significant latency.

### TCP handshake

Once the IP address is known, the browser sets up a connection to the server via a TCP three-way handshake. This mechanism is designed so that two entities attempting to communicate — in this case the browser and web server — can negotiate the parameters of the network TCP socket connection before transmitting data, often over HTTPS.

TCP's three-way handshaking technique is often referred to as "SYN-SYN-ACK" — or more accurately SYN, SYN-ACK, ACK — because there are three messages transmitted by TCP to negotiate and start a TCP session between two computers. Yes, this means three more messages back and forth between each server, and the request has yet to be made.

### TLS negotiation

For secure connections established over HTTPS, another "handshake" is required. This handshake, or rather the TLS negotiation, determines which cipher will be used to encrypt the communication, verifies the server, and establishes that a secure connection is in place before beginning the actual transfer of data. This requires five more round trips to the server before the request for content is actually sent.

![The DNS lookup, the TCP handshake, and 5 steps of the TLS handshake including clienthello, serverhello and certificate, clientkey and finished for both server and client.](/en-US/docs/Web/Performance/How_browsers_work/ssl.jpg)

While making the connection secure adds time to the page load, a secure connection is worth the latency expense, as the data transmitted between the browser and the web server cannot be decrypted by a third party.

After the eight round trips to the server, the browser is finally able to make the request.

Response
--------

Once we have an established connection to a web server, the browser sends an initial HTTP `GET` request on behalf of the user, which for websites is most often an HTML file. Once the server receives the request, it will reply with relevant response headers and the contents of the HTML.

```html
<!doctype html>
<html lang="en-US">
  <head>
    <meta charset="UTF-8" />
    <title>My simple page</title>
    <link rel="stylesheet" href="styles.css" />
    <script src="myscript.js"></script>
  </head>
  <body>
    <h1 class="heading">My Page</h1>
    <p>A paragraph with a <a href="https://example.com/about">link</a></p>
    <div>
      <img src="myimage.jpg" alt="image description" />
    </div>
    <script src="anotherscript.js"></script>
  </body>
</html>
```

This response for this initial request contains the first byte of data received. Time to First Byte (TTFB) is the time between when the user made the request — say by clicking on a link — and the receipt of this first packet of HTML. The first chunk of content is usually 14KB of data.

In our example above, the request is definitely less than 14KB, but the linked resources aren't requested until the browser encounters the links during parsing, described below.

### Congestion control / TCP slow start

TCP packets are split into segments during transmission. Because TCP guarantees the sequence of packets, the server must receive an acknowledgment from the client in the form of an ACK packet after sending a certain number of segments.

If the server waits for an ACK after each segment, that will result in frequent ACKs from the client and may increase transmission time, even in the case of a low-load network.

On the other hand, sending too many segments at once can lead to the problem that in a busy network the client will not be able to receive the segments and will just keep responding with ACKs for a long time, and the server will have to keep re-sending the segments.

In order to balance the number of transmitted segments, the TCP slow start algorithm is used to gradually increase the amount of transmitted data until the maximum network bandwidth can be determined, and to reduce the amount of transmitted data in case of high network load.

The number of segments to be transmitted is controlled by the value of the congestion window (CWND), which can be initialized to 1, 2, 4, or 10 MSS (MSS is 1500 bytes over the Ethernet protocol). That value is the number of bytes to send, upon receipt of which the client must send an ACK.

If an ACK is received, then the CWND value will be doubled, and so the server will be able to send more segments the next time. If instead no ACK is received, then the CWND value will be halved. That mechanism thus achieves a balance between sending too many segments, and sending too few.

Parsing
-------

Once the browser receives the first chunk of data, it can begin parsing the information received. Parsing is the step the browser takes to turn the data it receives over the network into the DOM and CSSOM, which is used by the renderer to paint a page to the screen.

The DOM is the internal representation of the markup for the browser. The DOM is also exposed and can be manipulated through various APIs in JavaScript.

Even if the requested page's HTML is larger than the initial 14KB packet, the browser will begin parsing and attempting to render an experience based on the data it has. This is why it's important for web performance optimization to include everything the browser needs to start rendering a page, or at least a template of the page — the CSS and HTML needed for the first render — in the first 14KB. But before anything is rendered to the screen, the HTML, CSS, and JavaScript have to be parsed.

### Building the DOM tree

We describe five steps in the critical rendering path.

The first step is processing the HTML markup and building the DOM tree. HTML parsing involves tokenization and tree construction. HTML tokens include start and end tags, as well as attribute names and values. If the document is well-formed, parsing it is straightforward and faster. The parser parses tokenized input into the document, building up the document tree.

The DOM tree describes the content of the document. The `<html>` element is the first element and root node of the document tree. The tree reflects the relationships and hierarchies between different elements. Elements nested within other elements are child nodes. The greater the number of DOM nodes, the longer it takes to construct the DOM tree.

![The DOM tree for our sample code, showing all the nodes, including text nodes.](/en-US/docs/Web/Performance/How_browsers_work/dom.gif)

When the parser finds non-blocking resources, such as an image, the browser will request those resources and continue parsing. Parsing can continue when a CSS file is encountered, but `<script>` elements — particularly those without an `async` or `defer` attribute — block rendering, and pause the parsing of HTML. Though the browser's preload scanner hastens this process, excessive scripts can still be a significant bottleneck.

### Preload scanner

While the browser builds the DOM tree, this process occupies the main thread. As this happens, the *preload scanner* will parse through the content available and request high-priority resources like CSS, JavaScript, and web fonts. Thanks to the preload scanner, we don't have to wait until the parser finds a reference to an external resource to request it. It will retrieve resources in the background so that by the time the main HTML parser reaches the requested assets, they may already be in flight or have been downloaded. The optimizations the preload scanner provides reduce blockages.

```html
<link rel="stylesheet" href="styles.css" />
<script src="myscript.js" async></script>
<img src="myimage.jpg" alt="image description" />
<script src="anotherscript.js" async></script>
```

In this example, while the main thread is parsing the HTML and CSS, the preload scanner will find the scripts and image, and start downloading them as well. To ensure the script doesn't block the process, add the `async` attribute, or the `defer` attribute if JavaScript parsing and execution order is important.

Waiting to obtain CSS doesn't block HTML parsing or downloading, but it does block JavaScript because JavaScript is often used to query CSS properties' impact on elements.

### Building the CSSOM tree

The second step in the critical rendering path is processing CSS and building the CSSOM tree. The CSS object model is similar to the DOM. The DOM and CSSOM are both trees. They are independent data structures. The browser converts the CSS rules into a map of styles it can understand and work with. The browser goes through each rule set in the CSS, creating a tree of nodes with parent, child, and sibling relationships based on the CSS selectors.

As with HTML, the browser needs to convert the received CSS rules into something it can work with. Hence, it repeats the HTML-to-object process, but for the CSS.

The CSSOM tree includes styles from the user agent style sheet. The browser begins with the most general rule applicable to a node and recursively refines the computed styles by applying more specific rules. In other words, it cascades the property values.

Building the CSSOM is very, very fast and is not displayed in a unique color in current developer tools. Rather, the "Recalculate Style" in developer tools shows the total time it takes to parse CSS, construct the CSSOM tree, and recursively calculate computed styles. In terms of web performance optimization, there are lower hanging fruit, as the total time to create the CSSOM is generally less than the time it takes for one DNS lookup.

### Other processes

#### JavaScript compilation

While the CSS is being parsed and the CSSOM created, other assets, including JavaScript files, are downloading (thanks to the preload scanner). JavaScript is parsed, compiled, and interpreted. The scripts are parsed into abstract syntax trees. Some browser engines take the abstract syntax trees and pass them into a compiler, outputting bytecode. This is known as JavaScript compilation. Most of the code is interpreted on the main thread, but there are exceptions such as code run in web workers.

#### Building the accessibility tree

The browser also builds an accessibility tree that assistive devices use to parse and interpret content. The accessibility object model (AOM) is like a semantic version of the DOM. The browser updates the accessibility tree when the DOM is updated. The accessibility tree is not modifiable by assistive technologies themselves.

Until the AOM is built, the content is not accessible to screen readers.

Render
------

Rendering steps include style, layout, paint, and in some cases compositing. The CSSOM and DOM trees created in the parsing step are combined into a render tree which is then used to compute the layout of every visible element, which is then painted to the screen. In some cases, content can be promoted to its own layer and composited, improving performance by painting portions of the screen on the GPU instead of the CPU, freeing up the main thread.

### Style

The third step in the critical rendering path is combining the DOM and CSSOM into a render tree. The computed style tree, or render tree, construction starts with the root of the DOM tree, traversing each visible node.

Elements that aren't going to be displayed, like the `<head>` element and its children and any nodes with `display: none`, such as the `script { display: none; }` you will find in user agent stylesheets, are not included in the render tree as they will not appear in the rendered output. Nodes with `visibility: hidden` applied are included in the render tree, as they do take up space. As we have not given any directives to override the user agent default, the `script` node in our code example above will not be included in the render tree.

Each visible node has its CSSOM rules applied to it. The render tree holds all the visible nodes with content and computed styles — matching up all the relevant styles to every visible node in the DOM tree, and determining, based on the CSS cascade, what the computed styles are for each node.

### Layout

The fourth step in the critical rendering path is running layout on the render tree to compute the geometry of each node. *Layout* is the process by which the dimensions and location of all the nodes in the render tree are determined, plus the determination of the size and position of each object on the page. *Reflow* is any subsequent size and position determination of any part of the page or the entire document.

Once the render tree is built, layout commences. The render tree identified which nodes are displayed (even if invisible) along with their computed styles, but not the dimensions or location of each node. To determine the exact size and position of each object, the browser starts at the root of the render tree and traverses it.

On the web page, almost everything is a box. Different devices and different desktop preferences mean an unlimited number of differing viewport sizes. In this phase, taking the viewport size into consideration, the browser determines what the sizes of all the different boxes are going to be on the screen. Taking the size of the viewport as its base, layout generally starts with the body, laying out the sizes of all the body's descendants, with each element's box model properties, providing placeholder space for replaced elements it doesn't know the dimensions of, such as our image.

The first time the size and position of each node is determined is called *layout*. Subsequent recalculations of are called *reflows*. In our example, suppose the initial layout occurs before the image is returned. Since we didn't declare the dimensions of our image, there will be a reflow once the image dimensions are known.

### Paint

The last step in the critical rendering path is painting the individual nodes to the screen, the first occurrence of which is called the first meaningful paint. In the painting or rasterization phase, the browser converts each box calculated in the layout phase to actual pixels on the screen. Painting involves drawing every visual part of an element to the screen, including text, colors, borders, shadows, and replaced elements like buttons and images. The browser needs to do this super quickly.

To ensure smooth scrolling and animation, everything occupying the main thread, including calculating styles, along with reflow and paint, must take the browser less than 16.67ms to accomplish. At 2048 x 1536, the iPad has over 3,145,000 pixels to be painted to the screen. That is a lot of pixels that have to be painted very quickly. To ensure repainting can be done even faster than the initial paint, the drawing to the screen is generally broken down into several layers. If this occurs, then compositing is necessary.

Painting can break the elements in the layout tree into layers. Promoting content into layers on the GPU (instead of the main thread on the CPU) improves paint and repaint performance. There are specific properties and elements that instantiate a layer, including `<video>` and `<canvas>`, and any element which has the CSS properties of `opacity`, a 3D `transform`, `will-change`, and a few others. These nodes will be painted onto their own layer, along with their descendants, unless a descendant necessitates its own layer for one (or more) of the above reasons.

Layers do improve performance but are expensive when it comes to memory management, so should not be overused as part of web performance optimization strategies.

### Compositing

When sections of the document are drawn in different layers, overlapping each other, compositing is necessary to ensure they are drawn to the screen in the right order and the content is rendered correctly.

As the page continues to load assets, reflows can happen (recall our example image that arrived late). A reflow sparks a repaint and a re-composite. Had we defined the dimensions of our image, no reflow would have been necessary, and only the layer that needed to be repainted would be repainted, and composited if necessary. But we didn't include the image dimensions! When the image is obtained from the server, the rendering process goes back to the layout steps and restarts from there.

Interactivity
-------------

Once the main thread is done painting the page, you would think we would be "all set." That isn't necessarily the case. If the load includes JavaScript, that was correctly deferred, and only executed after the `onload` event fires, the main thread might be busy, and not available for scrolling, touch, and other interactions.

Time to Interactive (TTI) is the measurement of how long it took from that first request which led to the DNS lookup and TCP connection to when the page is interactive — interactive being the point in time after the First Contentful Paint when the page responds to user interactions within 50ms. If the main thread is occupied parsing, compiling, and executing JavaScript, it is not available and therefore not able to respond to user interactions in a timely (less than 50ms) fashion.

In our example, maybe the image loaded quickly, but perhaps the `anotherscript.js` file was 2MB and our user's network connection was slow. In this case, the user would see the page super quickly, but wouldn't be able to scroll without jank until the script was downloaded, parsed, and executed. That is not a good user experience. Avoid occupying the main thread, as demonstrated in this WebPageTest example:

![The main thread is occupied by the downloading, parsing and execution of a JavaScript file - over a fast connection](/en-US/docs/Web/Performance/How_browsers_work/visa_network.png)

In this example, JavaScript execution took over 1.5 seconds, and the main thread was fully occupied that entire time, unresponsive to click events or screen taps.

See also
--------

* Web Performance


Navigation and resource timings - Web performance

Navigation and resource timings
===============================

**Navigation timings** are metrics measuring a browser's document navigation events. **Resource timings** are detailed network timing measurements regarding the loading of an application's resources. Both provide the same read-only properties, but navigation timing measures the main document's timings whereas the resource timing provides the times for all the assets or resources called in by that main document and the resources' requested resources.

The general performance timings below have been deprecated in favor of the Performance Entry API, which provides for marking and measuring times along the navigation and resource loading process. While deprecated, they are supported in all browsers.

Performance Timings
-------------------

The performanceTiming API, a JavaScript API for measuring the loading performance of the requested page, is deprecated but supported in all browsers. It has been replaced with the performanceNavigationTiming API.

The performance timing API provided read only times, in milliseconds(ms), describing at what time each point in the page loading process was reached. As displayed in the image below, the navigation process goes from `navigationStart`, `unloadEventStart`, `unloadEventEnd`, `redirectStart`, `redirectEnd`, `fetchStart`, `domainLookupStart`, `domainLookupEnd`, `connectStart`, `connectEnd`, `secureConnectionStart`, `requestStart`, `responseStart`, `responseEnd`, `domLoading`, `domInteractive`, `domContentLoadedEventStart`, `domContentLoadedEventEnd`, `domComplete`, `loadEventStart`, and `loadEventEnd`.

![Navigation Timing event metrics](/en-US/docs/Web/Performance/Navigation_and_resource_timings/screen_shot_2019-05-03_at_1.06.27_pm.png)

With the metrics above, and a bit of math, we can calculate many important metrics like time to first byte, page load time, dns lookup, and whether the connection is secure.

To help measure the time it takes to complete all the steps, the Performance Timing API provides read only measurements of navigation timings. To view and capture our app's timing we enter:

```js
let time = window.performance.timing;
```

We can then use the results to measure how well our app is performing.

![entering window.performance.timing in the console lists all the timings in the PerformanceNavigationTiming interface](/en-US/docs/Web/Performance/Navigation_and_resource_timings/navigatortiming.png)

The order is:

| Performance Timings | Details |
| --- | --- |
| `navigationStart` |
 When the prompt for unload terminates on the previous document in the
 same browsing context. If there is no previous document, this value will
 be the same as `PerformanceTiming.fetchStart`.
  |
| `secureConnectionStart` |
 When the secure connection handshake starts. If no such connection is
 requested, it returns `0`.
  |
| `redirectStart` |
 When the first HTTP redirect starts. If there is no redirect, or if one
 of the redirects is not of the same origin, the value returned is
 `0`.
  |
| `redirectEnd` |
 When the last HTTP redirect is completed, that is when the last byte
 of the HTTP response has been received. If there is no redirect, or if
 one of the redirects is not of the same origin, the value returned is
 `0`.
  |
| `connectEnd` |
 When the connection is opened network. If the transport layer reports an
 error and the connection establishment is started again, the last
 connection establishment end time is given. If a persistent connection
 is used, the value will be the same as
 `PerformanceTiming.fetchStart`. A connection is considered as
 opened when all secure connection handshake, or SOCKS authentication, is
 terminated.
  |
| `connectStart` |
 When the request to open a connection is sent to the network. If the
 transport layer reports an error and the connection establishment is
 started again, the last connection establishment start time is given. If
 a persistent connection is used, the value will be the same as
 `PerformanceTiming.fetchStart`.
  |
| `domainLookupEnd` |
 When the domain lookup is finished. If a persistent connection is used,
 or the information is stored in a cache or a local resource, the value
 will be the same as `PerformanceTiming.fetchStart`.
  |
| `domainLookupStart` |
 When the domain lookup starts. If a persistent connection is used, or
 the information is stored in a cache or a local resource, the value will
 be the same as `PerformanceTiming.fetchStart`.
  |
| `fetchStart` |
 When the browser is ready to fetch the document using an HTTP request.
 This moment is *before* the check to any application cache.
  |
| `requestStart` |
 When the browser sent the request to obtain the actual document, from
 the server or from a cache. If the transport layer fails after the start
 of the request and the connection is reopened, this property will be set
 to the time corresponding to the new request.
  |
| `responseStart` |
 When the browser received the first byte of the response, from the
 server from a cache, or from a local resource.
  |
| `responseEnd` |
 When the browser received the last byte of the response, or when the
 connection is closed if this happened first, from the server, the cache,
 or from a local resource.
  |
| `domLoading` |
 When the parser started its work, that is when its
 `Document.readyState` changes to
 `'loading'` and the corresponding
 `readystatechange`
 event is thrown.
  |
| `unloadEventStart` |
 When the `unload`>
 event has been thrown, indicating the time at which the previous
 document in the window began to unload. If there is no previous
 document, or if the previous document or one of the needed redirects is
 not of the same origin, the value returned is `0`.
  |
| `unloadEventEnd` |
 When the
 `unload`
 event handler finishes. If there is no previous document, or if the
 previous document, or one of the needed redirects, is not of the same
 origin, the value returned is `0`.
  |
| `domInteractive` |
 When the parser finished its work on the main document, that is when its
 `Document.readyState`
 changes to `'interactive'` and the corresponding
 `readystatechange`
 event is thrown.
  |
| `domContentLoadedEventStart` |
 Right before the parser sent the
 `DOMContentLoaded`
 event, that is right after all the scripts that need to be executed
 right after parsing have been executed.
  |
| `domContentLoadedEventEnd` |
 Right after all the scripts that need to be executed as soon as
 possible, in order or not, have been executed.
  |
| `domComplete` |
 When the parser finished its work on the main document, that is when its
 `Document.readyState`
 changes to `'complete'` and the corresponding
 `readystatechange`
 event is thrown.
  |
| `loadEventStart` |
 When the
 `load`
 event was sent for the current document. If this event has not yet been
 sent, it returns `0.` |
| `loadEventEnd` |
 When the
 `load`
 event handler terminated, that is when the load event is completed. If
 this event has not yet been sent, or is not yet completed, it returns
 `0.` |

### Calculating timings

We can use these values to measure specific timings of interest:

```js
const dns = time.domainLookupEnd - time.domainLookupStart;
const tcp = time.connectEnd - time.connectStart;
const tls = time.requestStart - time.secureConnectionStart;
```

### Time to first byte

Time to First Byte is the time between the `navigationStart` (start of the navigation) and `responseStart`, (when the first byte of response data is received) available in the `performanceTiming` API:

```js
const ttfb = time.responseStart - time.navigationStart;
```

### Page load time

Page load time is the time between `navigationStart` and the start of when the load event is sent for the current document. They are only available in the performanceTiming API.

```js
let pageloadtime = time.loadEventStart - time.navigationStart;
```

### DNS lookup time

The DNS lookup time is the time between `domainLookupStart` and `domainLookupEnd`. These are both available in both the `performanceTiming` and `performanceNavigationTiming` APIs.

```js
const dns = time.domainLookupEnd - time.domainLookupStart;
```

### TCP

The time it takes for the TCP handshake is the time between the connection start and connection end:

```js
const tcp = time.connectEnd - time.connectStart;
```

### TLS negotiation

`secureConnectionStart` will be `undefined` if not available, `0` if HTTPS in not used, or a timestamp if available, and used. In other words, if a secure connection was used, `secureConnectionStart` will be truthy, and the time between `secureConnectionStart` and `requestStart` will greater than 0.

```js
const tls = time.requestStart - time.secureConnectionStart;
```

Performance Entry API
---------------------

The general performance timings above are deprecated but fully supported. We now have the `Performance Entry API`, which provides for marking and measuring times along the navigation and resource loading process. You can also create marks:

```js
performance.getEntriesByType("navigation").forEach((navigation) => {
  console.dir(navigation);
});

performance.getEntriesByType("resource").forEach((resource) => {
  console.dir(resource);
});

performance.getEntriesByType("mark").forEach((mark) => {
  console.dir(mark);
});

performance.getEntriesByType("measure").forEach((measure) => {
  console.dir(measure);
});

performance.getEntriesByType("paint").forEach((paint) => {
  console.dir(paint);
});

performance.getEntriesByType("frame").forEach((frame) => {
  console.dir(frame);
});
```

In supporting browsers, you can use `performance.getEntriesByType('paint')` to query the measure for `first-paint` and `first-contentful-paint`. We use `performance.getEntriesByType('navigation')` and `performance.getEntriesByType('resource')` to query the navigation and resource timings respectively.

Navigation Timing
-----------------

When a user requests a website or application, to populate the browser the user agent goes through a series of steps, including a DNS lookup, TCP handshake, and TLS negotiation, before the user agent makes the actual request and the servers return the requested assets. The browser then parses the content received, builds the DOM, CSSOM, accessibility, and render trees, eventually rendering the page. Once the user agent stops parsing the document, the user agent sets the document readiness to *interactive*. If there are deferred scripts needing to be parsed, it will do so, then fire the DOMContentLoaded, after which the readiness is set to *complete*. The Document can now handle post-load tasks, after which point the document is marked as completely loaded.

```js
const navigationTimings = performance.getEntriesByType("navigation");
```

The `performance.getEntriesByType('navigation')` a returns an array of PerformanceEntry objects for the *navigation* *type*.

![The results of when performance.getEntriesByType('navigation'); is entered into the console for this document](/en-US/docs/Web/Performance/Navigation_and_resource_timings/perfgentrybytypenavigation.png)

A lot can be garnered from these timing. In the above image, we see via the *name* property that the file being timed is this document For the rest of this explanation, we use the following variable:

```js
const timing = performance.getEntriesByType("navigation")[0];
```

### Protocol

We can check the protocol used by querying:

```js
const protocol = timing.nextHopProtocol;
```

It returns the network protocol used to fetch the resource: in this case `h2` for `http/2`.

### Compression

To get the compression savings percentage, we divide the transferSize by the decodedBodySize, and subtract that from 100%. We see a savings of over 74%.

```js
const compressionSavings = 1 - timing.transferSize / timing.decodedBodySize;
```

We could have used

```js
const compressionSavings = 1 - timing.encodedBodySize / timing.decodedBodySize;
```

but using `transferSize` includes the overhead bytes.

For comparison, we can look at the network tab and see that we transferred 22.04KB for an uncompressed file size of 87.24KB.

![View of the bytes transferred and the size via the network tab](/en-US/docs/Web/Performance/Navigation_and_resource_timings/bytesdownloaded.png)

If we do the math with these numbers, we get the same result: `1 - (22.04 / 87.24) = 0.747`. The navigation timings provide us a way to programmatically check transfer sizing and bandwidth savings.

Note that this is the size for this single document alone: for this resource alone, not for all the resources combined. However, the duration, load events and DOM related timings have to do with the entire navigation, not this single asset. Client-side web applications may seem faster than this one with transfer sizes under 10000 and decoded body sizes under 30000, but that doesn't mean JavaScript, CSS, or media assets aren't adding bloat. Checking compression ratios is important but ensure to also check duration and the time between when the DOMContentLoaded event ended and when the DOM is complete, as running JavaScript on the main thread for long periods of time can lead to a non-responsive user interface.

### Request time

The API doesn't provide every measurement you may desire. For example, how long did the request take? We can use measurements we do have, to get our answer.

To measure the response time, subtract the request start time from the response start time. The request start is the moment immediately before the user agent starts requesting the resource from the server, or from relevant application caches or from local resources. The response start is the time immediately after the user agent's HTTP parser receives the first byte of the response from relevant application caches, or from local resources or from the server, which happens after the request is received and processed.

```js
const request = timing.responseStart - timing.requestStart;
```

### Load event duration

By subtracting the timestamp from immediately before the load event of the current document is fired from the time when the load event of the current document is completed, you can measure the duration of the load event.

```js
const load = timing.loadEventEnd - timing.loadEventStart;
```

### DOMContentLoaded event

The DOMContentLoaded event duration is measured by subtracting the time value immediately before the user agent fires the DOMContentLoaded event from the time value immediately after the event completes. Keeping this at 50ms or faster helps ensure a responsive user interface.

```js
const DOMContentLoaded =
  timing.domContentLoadedEventEnd - timing.domContentLoadedEventStart;
```

### Duration

We are provided with the duration. The duration is the difference between the PerformanceNavigationTiming.loadEventEnd and PerformanceEntry.startTime properties.

The PerformanceNavigationTiming interface also provides information about what type of navigation you are measuring, returning `navigate`, `reload`, `back_forward` or `prerender`.

Resource timing
---------------

Whereas navigation timing is for measuring the performance of the *main page*, generally the HTML file via which all the other assets are requested, resource timing measures timing for *individual resources*, the assets called in by the main page, and any assets that those resources request. Many of the measurements are similar: there is a DNS look up, TCP handshake and the secure connection start is done once per domain.

![Graphic of Resource Timing timestamps](/en-US/docs/Web/Performance/Navigation_and_resource_timings/resourcetiming-timestamps.jpg)

The main thing to look at for each resource.

See also
--------

* `PerformanceNavigationTiming`
* `PerformanceResourceTiming`,
* `PerformanceMark`
* `PerformanceMeasure`
* `PerformancePaintTiming`


Lazy loading - Web performance

Lazy loading
============

**Lazy loading** is a strategy to identify resources as non-blocking (non-critical) and load these only when needed. It's a way to shorten the length of the critical rendering path, which translates into reduced page load times.

Lazy loading can occur on different moments in the application, but it typically happens on some user interactions such as scrolling and navigation.

Overview
--------

 As the web has evolved, we have come to see huge increases in the number and size of assets sent to users.
 Between 2011 and 2019, the median resource weight increased from **~100KB** to **~400KB** for desktop and **~50KB** to **~350KB** for mobile. While Image size has increased from **~250KB** to **~900KB** on desktop and **~100KB** to **~850KB** on mobile.

 One of the methods we can use to tackle this problem is to shorten the Critical Rendering Path length by lazy loading resources that are not critical for the first render to happen.
 A practical example would be when you land on the home page of an e-commerce site with a link to a cart page/section, and none of the cart page's resources (such as JavaScript, CSS, and images) are downloaded **until** you navigate there.

Strategies
----------

Lazy loading can be applied to multiple resources and through multiple strategies.

### General

#### Code splitting

JavaScript, CSS and HTML can be split into smaller chunks. This enables sending the minimal code required to provide value upfront, improving page-load times. The rest can be loaded on demand.

* Entry point splitting: separates code by entry point(s) in the app
* Dynamic splitting: separates code where dynamic import() expressions are used
### JavaScript

#### Script type module

Any script tag with `type="module"` is treated as a JavaScript module and is deferred by default.

### CSS

By default, CSS is treated as a render blocking resource, so the browser won't render any processed content until the CSSOM is constructed. CSS must be thin, delivered as quickly as possible, and the usage media types and queries are advised to unblock rendering.

```html
<link href="style.css" rel="stylesheet" media="all" />
<link href="portrait.css" rel="stylesheet" media="(orientation:portrait)" />
<link href="print.css" rel="stylesheet" media="print" />
```

It is possible to perform some CSS optimizations to achieve that.

### Fonts

By default, font requests are delayed until the render tree is constructed, which can result in delayed text rendering.

It is possible to override the default behavior and preload web font resources using `<link rel="preload">`, the CSS font-display property, and the Font Loading API.

See also: Element Link.

### Images and iframes

Very often, webpages contain many images that contribute to data-usage and how fast a page can load. Most of those images are off-screen (non-critical), requiring a user interaction, like scrolling, in order to view them.

#### Loading attribute

 The `loading` attribute on an `<img>` element, or the `loading` attribute on an `<iframe>`, can be used to instruct the browser to defer loading of images/iframes that are off-screen until the user scrolls near them.
 This allows non-critical resources to load only if needed, potentially speeding up initial page loads and reducing network usage.

```html
<img loading="lazy" src="image.jpg" alt="..." />
<iframe loading="lazy" src="video-player.html" title="..."></iframe>
```

The `load` event fires when the eagerly-loaded content has all been loaded. At that time, it's entirely possible (or even likely) that there may be lazily-loaded images or iframes within the visual viewport that haven't yet loaded.

You can determine if a given image has finished loading by examining the value of its Boolean `complete` property.

#### Intersection Observer API

Intersection Observers allow the user to know when an observed element enters or exits the browser's viewport.

#### Event handlers

When browser compatibility is crucial, there are a few options:

* polyfill intersection observer
* fallback to scroll, resize or orientation change event handlers to determine if a specific element is in viewport
Specifications
--------------

| Specification |
| --- |
| HTML Standard # lazy-loading-attributes |

See also
--------

* Render blocking CSS
* Use lazy loading to improve loading speed


CSS and JavaScript animation performance - Web performance

CSS and JavaScript animation performance
========================================

Animations are critical for a pleasurable user experience on many applications. There are many ways to implement web animations, such as CSS `transitions`/`animations` or JavaScript-based animations (using `requestAnimationFrame()`). In this article, we analyze the performance differences between CSS-based and JavaScript-based animation.

CSS transitions and animations
------------------------------

Both CSS transitions and animations can be used to write animation. They each have their own user scenarios:

* CSS `transitions` provide an easy way to make animations occur between the current style and an end CSS state, e.g., a resting button state and a hover state. Even if an element is in the middle of a transition, the new transition starts from the current style immediately instead of jumping to the end CSS state. See Using CSS transitions for more details.
* CSS `animations`, on the other hand, allow developers to make animations between a set of starting property values and a final set rather than between two states. CSS animations consist of two components: a style describing the CSS animation, and a set of key frames that indicate the start and end states of the animation's style, as well as possible intermediate points. See Using CSS animations for more details.

In terms of performance, there is no difference between implementing an animation with CSS transitions or animations. Both of them are classified under the same CSS-based umbrella in this article.

requestAnimationFrame
---------------------

The `requestAnimationFrame()` API provides an efficient way to make animations in JavaScript. The callback function of the method is called by the browser before the next repaint on each frame. Compared to `setTimeout()`/`setInterval()`, which need a specific delay parameter, `requestAnimationFrame()` is much more efficient. Developers can create an animation by changing an element's style each time the loop is called (or updating the Canvas draw, or whatever.)

**Note:** Like CSS transitions and animations, `requestAnimationFrame()` pauses when the current tab is pushed into the background.

For more details read animating with JavaScript from setInterval to requestAnimationFrame.

Performance comparison:transitions vs. requestAnimationFrame
------------------------------------------------------------

The fact is that, in most cases, the performance of CSS-based animations is almost the same as JavaScripted animations — in Firefox at least. Some JavaScript-based animation libraries, like GSAP and Velocity.JS, even claim that they are able to achieve better performance than native CSS transitions/animations. This can occur because CSS transitions/animations are resampling element styles in the main UI thread before each repaint event happens, which is almost the same as resampling element styles via a `requestAnimationFrame()` callback, also triggered before the next repaint. If both animations are made in the main UI thread, there is no difference performance-wise.

In this section we'll walk you through a performance test, using Firefox, to see what animation method seems better overall.

### Enabling FPS tools

Before going through the example, please enable FPS tools first to see the current frame rate:

1. In the URL bar, enter *about:config*; click the `I'll be careful, I promise!` button to enter the config screen.

 ![Warning screen that changing settings can be risky, with a button to accept risks.](/en-US/docs/Web/Performance/CSS_JavaScript_animation_performance/pic1.png)
2. In the search bar, search for the `layers.acceleration.draw-fps` preference.
3. Double-click the entry to set the value to `true`. Now you will be able to see three little purple boxes in the upper left corner of the Firefox window. The first box represents FPS.

 ![Entering the search term filters the options. Only the layers.acceleration.draw-fps preference is showing and is set to true. Three numbers (001, 001, and 108) are appearing in the upper left corner of the browser, overlaying its UI.](/en-US/docs/Web/Performance/CSS_JavaScript_animation_performance/pic2.png)
### Running the performance test

Initially in the test seen below, a total of 1000 `<div>` elements are transformed by CSS animation.

```js
const boxes = [];
const button = document.getElementById("toggle-button");
const boxContainer = document.getElementById("box-container");
const animationType = document.getElementById("type");

// create boxes
for (let i = 0; i < 1000; i++) {
  const div = document.createElement("div");
  div.classList.add("css-animation");
  div.classList.add("box");
  boxContainer.appendChild(div);
  boxes.push(div.style);
}

let toggleStatus = true;
let rafId;
button.addEventListener("click", () => {
  if (toggleStatus) {
    animationType.textContent = " requestAnimationFrame";
    for (const child of boxContainer.children) {
      child.classList.remove("css-animation");
    }
    rafId = window.requestAnimationFrame(animate);
  } else {
    window.cancelAnimationFrame(rafId);
    animationType.textContent = " CSS animation";
    for (const child of boxContainer.children) {
      child.classList.add("css-animation");
    }
  }
  toggleStatus = !toggleStatus;
});

const duration = 6000;
const translateX = 500;
const rotate = 360;
const scale = 1.4 - 0.6;
let start;
function animate(time) {
  if (!start) {
    start = time;
    rafId = window.requestAnimationFrame(animate);
    return;
  }

  const progress = (time - start) / duration;
  if (progress < 2) {
    let x = progress \* translateX;
    let transform;
    if (progress >= 1) {
      x = (2 - progress) \* translateX;
      transform = `translateX(${x}px) rotate(${
 (2 - progress) \* rotate
 }deg) scale(${0.6 + (2 - progress) \* scale})`;
    } else {
      transform = `translateX(${x}px) rotate(${progress \* rotate}deg) scale(${
 0.6 + progress \* scale
 })`;
    }

    for (const box of boxes) {
      box.transform = transform;
    }
  } else {
    start = null;
  }
  rafId = window.requestAnimationFrame(animate);
}
```

```
<div id="header">
  <button id="toggle-button">Toggle</button>
  <span id="type">CSS Animation</span>
</div>
<div id="box-container"></div>
```

```
#header {
  position: sticky;
  top: 0.5rem;
  margin: 0 0.5rem;
  z-index: 100;
  background-color: lightgreen;
}

#box-container {
  margin-top: 1.5rem;
  display: grid;
  grid-template-columns: repeat(40, 1fr);
  gap: 15px;
}

.box {
  width: 30px;
  height: 30px;
  background-color: red;
}

.css-animation {
  animation: animate 6s linear 0s infinite alternate;
}

@keyframes animate {
  0% {
    transform: translateX(0) rotate(0deg) scale(0.6);
  }
  100% {
    transform: translateX(500px) rotate(360deg) scale(1.4);
  }
}
```

The animation can be switched to `requestAnimationFrame()` by clicking the toggle button.

Try running them both now, comparing the FPS for each (the first purple box.) You should see that the performance of CSS animations and `requestAnimationFrame()` are very close.

### Off main thread animation

Even given the test results above, we'd argue that CSS animations are the better choice. But how? The key is that as long as the properties we want to animate do not trigger reflow/repaint (read CSS triggers for more information), we can move those sampling operations out of the main thread. The most common property is the CSS transform. If an element is promoted as a layer, animating transform properties can be done in the GPU, meaning better performance/efficiency, especially on mobile. Find out more details in OffMainThreadCompositing.

To enable the OMTA (Off Main Thread Animation) in Firefox, you can go to *about:config* and search for the `layers.offmainthreadcomposition.async-animations`. Toggle its value to `true`.

![Entering the search term filters the options. Only the layers.offmainthreadcomposition.async-animations preference is showing, set to true. The three numbers in the upper left corner of the browser, above its UI, have increased to 005, 003, and 108.](/en-US/docs/Web/Performance/CSS_JavaScript_animation_performance/pic3.png)

After enabling OMTA, try running the above test again. You should see that the FPS of the CSS animations will now be significantly higher.

**Note:** In Nightly/Developer Edition, you should see that OMTA is enabled by default, so you might have to do the tests the other way around (test with it enabled first, then disable to test without OMTA.)

Summary
-------

Browsers are able to optimize rendering flows. In summary, we should always try to create our animations using CSS transitions/animations where possible. If your animations are really complex, you may have to rely on JavaScript-based animations instead.


Speculative loading - Web performance

Speculative loading
===================

**Speculative loading** refers to the practice of performing navigation actions (such as DNS fetching, fetching resources, or rendering documents) before the associated pages are actually visited, based on predictions as to what pages the user is most likely to visit next.

These predictions can be supplied by developers (for example, lists of the most popular destinations on their site) or determined by browser heuristics (for example based on popular sites in the user's history). When used successfully, such technologies can significantly improve performance by making pages available more quickly, or in some cases, instantly.

This page reviews available speculative loading technologies and when they can and should be used to improve performance.

Speculative loading mechanisms
------------------------------

There are several mechanisms for speculative loading:

* **Prefetching** involves fetching some or all of the resources required to render a document (or part of a document) before they are needed, so that when the time comes to render it, rendering can be achieved much more quickly.
* **Prerendering** goes a step further, and actually renders the content ready to be shown when required. Depending on how this is done, this can result in an instant navigation from old page to new page.
* **Preconnecting** involves speeding up future loads from a given origin by preemptively performing part or all of the connection handshake (i.e. DNS + TCP + TLS).

**Note:** The above descriptions are high-level and general. Exactly what browsers will do to achieve prefetching and prerendering depends on the features used. More exact feature descriptions are provided in the Speculative loading features section below.

How is speculative loading achieved?
------------------------------------

Speculative loading is achieved in two main ways.

First, some browsers will automatically prerender pages based on various heuristics to provide automatic performance improvements. Exactly how this is done depends on the browser implementation. Chrome, for example, automatically prerenders pages when matching strings are typed into the address bar — if it has a high confidence that you will visit that page (see Viewing Chrome's address bar predictions for more details). In addition, it may automatically prerender search results pages when search terms are typed into the address bar, when instructed to do so by the search engine. It does this using the same mechanism as the Speculation Rules API.

Second, there are several different platform features that developers can use to provide instructions on what speculative loading they want the browser to perform. These are reviewed in the next section.

Speculative loading features
----------------------------

### `<link rel="preconnect">`

`<link rel="preconnect">` provides a hint to browsers that the user is likely to need resources from the specified resource's origin, and therefore the browser can likely improve performance by preemptively initiating a connection to that origin. Supporting browsers will preemptively perform part or all of the connection handshake (i.e. DNS + TCP + TLS).

For example:

```html
<link rel="preconnect" href="https://example.com" />
```

`<link rel="preconnect">` is widely supported across browsers, and will provide a benefit to any future cross-origin HTTP request, navigation or subresource. It has no benefit on same-origin requests because the connection is already open.

If a page needs to make connections to many third-party domains, preconnecting them all can be counterproductive. The `<link rel="preconnect">` hint is best used for only the most critical connections. For the others, just use `<link rel="dns-prefetch">` to save time on the first step — the DNS lookup.

You can also implement preconnect as an HTTP Link header, for example:

```http
Link: <https://example.com>; rel="preconnect"
```

### `<link rel="dns-prefetch">`

`<link rel="dns-prefetch">` provides a hint to browsers that the user is likely to need resources from the specified resource's origin, and therefore the browser may be able to improve performance by preemptively performing DNS resolution for that origin. It is identical to `<link rel="preconnect">` except that it only handles the DNS part.

Again, browser support is widespread, and it has no benefit on same-origin requests because the connection is already open.

For example:

```html
<link rel="dns-prefetch" href="https://example.com" />
```

**Note:** See Using dns-prefetch for more details.

### `<link rel="preload">`

`<link rel="preload">` provides a hint to browsers as to what resources are high-priority on *the current page*, so it can start downloading them early when it sees the `<link>` element(s) in the `<head>` of the page.

For example:

```html
<link rel="preload" href="main.js" as="script" />
<!-- CORS-enabled preload -->
<link
 rel="preload"
 href="https://www.example.com/fonts/cicle\_fina-webfont.woff2"
 as="font"
 type="font/woff2"
 crossorigin />
```

The result is kept in a per-document in-memory cache. If you preload something your current page doesn't use as a subresource, it is generally a waste of resources, although the result may populate the HTTP cache if headers allow.

You can also implement preload as an HTTP Link header, for example:

```http
Link: <https://www.example.com/fonts/cicle\_fina-webfont.woff2>; rel="preload"
```

Browser support for `<link rel="preload">`/`<link rel="modulepreload">` is widespread in modern browsers.

### `<link rel="modulepreload">`

`<link rel="modulepreload">` provides a hint to browsers as to what JavaScript modules are high-priority on *the current page*, so it can start downloading them early.

For example:

```js
<link rel="modulepreload" href="main.js" />
```

It is a specialized version of `<link rel="preload">` for JavaScript modules and works basically the same way. However, there are some differences:

* The browser knows the resource is a JavaScript module, as the `as` attribute is not needed, and it can use the correct credentials modes to avoid double-fetching.
* Rather than just downloading it and storing it in a cache, the browser downloads it, then parses and compiles it directly into the in-memory module map.
* The browser can also do the same for module dependencies automatically.
### `<link rel="prefetch">`

`<link rel="prefetch">` provides a hint to browsers that the user is likely to need the target resource for future navigations, and therefore the browser can likely improve the user experience by preemptively fetching and caching the resource. `<link rel="prefetch">` is used for same-site navigation resources, or for subresources used by same-site pages.

For example:

```js
<link rel="prefetch" href="main.js" />
```

Prefetching can be used to fetch both HTML and sub-resources for a possible next navigation. A common use case is to have a simple website landing page that fetches more "heavy-weight" resources used by the rest of the site.

```html
<link rel="prefetch" href="/app/style.css" />
<link rel="prefetch" href="/landing-page" />
```

The result is kept in the HTTP cache on disk. Because of this it is useful for prefetching subresources, even if they are not used by the current page. You could also use it to prefetch the next document the user will likely visit on the site. However, as a result you need to be careful with headers — for example certain Cache-Control headers could block prefetching (for example `no-cache` or `no-store`).

Many browsers now implement some form of cache partitioning, which makes `<link rel="prefetch">` useless for resources intended for use by different top-level sites. This includes the main document when navigating cross-site. So, for example, the following prefetch:

```html
<link rel="prefetch" href="https://news.example/article" />
```

Would not be accessible from `https://aggregator.example/`.

**Note:** `<link rel="prefetch">` is functionally equivalent to a `fetch()` call with a `priority: "low"` option set on it, except that the former will generally have an even lower priority, and it will have a `Sec-Purpose: prefetch` header set on the request.

**Note:** The fetch request for a `prefetch` operation results in an HTTP Request that includes the HTTP header `Sec-Purpose: prefetch`. A server might use this header to change the cache timeouts for the resources, or perform other special handling.
 The request will also include the `Sec-Fetch-Dest` header with the value set to `empty`.
 The `Accept` header in the request will match the value used for normal navigation requests. This allows the browser to find the matching cached resources following navigation.
 If a response is returned, it gets cached with the request in the HTTP cache.

### `<link rel="prerender">`
Deprecated

Non-standard

**Note:** This technology was only ever available in Chrome, and is now deprecated. You should use the Speculation Rules API instead, which supercedes this.

`<link rel="prerender">` provides a hint to browsers that the user might need the target resource for the next navigation, and therefore the browser can likely improve performance by prerendering the resource. `prerender` is used for future navigations, same-site only, and as such makes sense for multi-page applications (MPAs), not single-page applications (SPAs).

For example:

```html
<link rel="prerender" href="/next-page" />
```

It will fetch the referenced document, then fetch any linked resources that are statically findable and fetch them too, storing the result in the HTTP cache on disk with a five-minute timeout. The exception is subresources loaded via JavaScript — it does not find these. It has other problems too — like `<link rel="prefetch">` it can also be blocked by Cache-Control headers, and be rendered useless for resources intended for use by different top-level sites by browser cache partitioning.

### Speculation Rules API

`<script type="speculationrules">` is used to provide a set of rules that determine what future documents should be prefetched or prerendered by the browser. This is part of the Speculation Rules API.

When should you use each feature?
---------------------------------

The following table summarizes the features detailed above, and provides guidance on when to use each one.

| Speculative loading features | Purpose | When to use |
| --- | --- | --- |
| `<link rel="preconnect">` | Cross-origin connection warming | Use on your most critical cross-origin connections to provide performance improvements when connecting to them. |
| `<link rel="dns-prefetch">` | Cross-origin connection warming | Use on all of your cross-origin connections to provide small performance improvements when connecting to them. |
| `<link rel="preload">` | High-priority loading of current page subresources | Use to load high-priority resources faster on the current page, for strategic performance improvements. Don't preload everything, otherwise you won't see the benefit. Also has some other interesting uses — see Preload: What Is It Good For? on Smashing Magazine (2016) |
| `<link rel="modulepreload">` | High-priority loading of current page JavaScript modules | Use to preload high-priority JavaScript modules for strategic performance improvements. |
| `<link rel="prefetch">` | Pre-populating the HTTP cache | Use to prefetch same-site future navigation resources or subresources used on those pages. Uses HTTP cache therefore has a number of issues with document prefetches, such as being potentially blocked by Cache-Control headers. Use the Speculation Rules API for document prefetches instead, where it is supported. |
| `<link rel="prerender">` | Preparing for the next navigation | Deprecated; you are advised not to use this. Use Speculation Rules API prerender instead, where it is supported. |
| Speculation Rules API prefetch | Preparing for the next navigation | Use to prefetch same or cross-site future navigation documents. Broad adoption is recommended, where it is supported; check to make sure the pages are safe to prefetch. It doesn't handle subresource prefetches; for that you'll need to use `<link rel="prefetch">`. |
| Speculation Rules API prerender | Preparing for the next navigation | Use to preload same-origin future navigation resources, for near-instant navigations. Use on high-priority pages, where it is supported; check to make sure the pages are safe to prerender. |

See also
--------

* Prerender pages in Chrome for instant page navigations on developer.chrome.com (2023)


Using dns-prefetch - Web performance

Using dns-prefetch
==================

**`DNS-prefetch`** is an attempt to resolve domain names before resources get requested. This could be a file loaded later or link target a user tries to follow.

Why use dns-prefetch?
---------------------

When a browser requests a resource from a (third party) server, that cross-origin's domain name must be resolved to an IP address before the browser can issue the request. This process is known as DNS resolution. While DNS caching can help to reduce this latency, DNS resolution can add significant latency to requests. For websites that open connections to many third parties, this latency can significantly reduce loading performance.

`dns-prefetch` helps developers mask DNS resolution latency. The HTML `<link>` element offers this functionality by way of a `rel` attribute value of `dns-prefetch`. The cross-origin domain is then specified in the href attribute:

Syntax
------

```html
<link rel="dns-prefetch" href="https://fonts.googleapis.com/" />
```

Examples
--------

```html
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width,initial-scale=1" />
    <link rel="dns-prefetch" href="https://fonts.googleapis.com/" />
    <!-- and all other head elements -->
  </head>
  <body>
    <!-- your page content -->
  </body>
</html>
```

You should place `dns-prefetch` hints in the `<head>` element any time your site references resources on cross-origin domains, but there are some things to keep in mind.

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

There are 3 main things to keep in mind:

**For one**, `dns-prefetch` is only effective for DNS lookups on cross-origin domains, so avoid using it to point to your site or domain. This is because the IP behind your site's domain will have already been resolved by the time the browser sees the hint.

**Second**, it's also possible to specify `dns-prefetch` (and other resources hints) as an HTTP header by using the HTTP Link field:

```http
Link: <https://fonts.googleapis.com/>; rel=dns-prefetch
```

**Third**, while `dns-prefetch` only performs a DNS lookup, `preconnect` establishes a connection to a server. This process includes DNS resolution, as well as establishing the TCP connection, and performing the TLS handshake—if a site is served over HTTPS. Using `preconnect` provides an opportunity to further reduce the perceived latency of cross-origin requests. You can use it as an HTTP header by using the HTTP Link field:

```http
Link: <https://fonts.googleapis.com/>; rel=preconnect
```

or via the HTML `<link>` element:

```html
<link rel="preconnect" href="https://fonts.googleapis.com/" crossorigin />
```

**Note:** If a page needs to make connections to many third-party domains, preconnecting them all is counterproductive. The `preconnect` hint is best used for only the most critical connections. For the others, just use `<link rel="dns-prefetch">` to save time on the first step — the DNS lookup.

The logic behind pairing these hints is because support for dns-prefetch is better than support for preconnect. Browsers that don't support preconnect will still get some added benefit by falling back to dns-prefetch. Because this is an HTML feature, it is very fault-tolerant. If a non-supporting browser encounters a dns-prefetch hint—or any other resource hint—your site won't break. You just won't receive the benefits it provides.

Some resources such as fonts are loaded in anonymous mode. In such cases you should set the crossorigin attribute with the preconnect hint. If you omit it, the browser will only perform the DNS lookup.

See also
--------

* <link>
* HTML attribute: rel
* crossorigin
* Cross-Origin Resource Sharing (CORS)
* HTTP headers
* HTTP header Link


Understanding latency - Web performance

Understanding latency
=====================

**Latency** is the time it takes for a packet of data to travel from source to a destination. In terms of performance optimization, it's important to optimize to reduce causes of latency and to test site performance emulating high latency to optimize for users with lousy connections. This article explains what latency is, how it impacts performance, how to measure latency, and how to reduce it.

What is Latency?
----------------

Latency is generally considered to be the amount of time it takes from when a request is made by the user to the time it takes for the response to get back to that user. On a first request, for the first 14Kb bytes, latency is longer because it includes a DNS lookup, a TCP handshake, the secure TLS negotiation. Subsequent requests will have less latency because the connection to the server is already set.

Latency describes the amount of delay on a network or Internet connection. Low latency implies that there are no or almost no delays. High latency implies that there are many delays. One of the main aims of improving performance is to reduce latency.

The latency associated with a single asset, especially a basic HTML page, may seem trivial. But websites generally involve multiple requests: the HTML includes requests for multiple CSS, scripts, and media files. The greater the number and size of these requests, the greater the impact of high latency on user experience.

On a connection with low latency, requested resources will appear almost immediately. On a connection with high latency, there will be a discernible delay between the time that a request is sent, and the resources are returned. We can determine the amount of latency by measuring the speed with which the data moves from one network location to another.

Latency can be measured one way, for example, the amount of time it takes to send a request for resources, or the length of the entire round-trip from the browser's request for a resource to the moment when the requested resource arrives at the browser.

Network throttling
------------------

To emulate the latency of a low bandwidth network, you can use developer tools and switch to a lower end network connection.

![Emulate latency by emulating throttling](/en-US/docs/Web/Performance/Understanding_latency/emulate_latency.png)

In the developer tools, under the network table, you can switch the throttling option to 2G, 3G, etc. Different browser developer tools have different preset options, the characteristics emulated include download speed, upload speed, and minimum latency, or the minimum amount of time it takes to send a packet of data. The approximate values of some presets include:

| Selection | Download speed | Upload speed | Minimum latency (ms) |
| --- | --- | --- | --- |
| GPRS | 50 Kbps | 20 Kbps | 500 |
| Regular 2G | 250 Kbps | 50 Kbps | 300 |
| Good 2G | 450 Kbps | 150 Kbps | 150 |
| Regular 3G | 750 Kbps | 250 Kbps | 100 |
| Good 3G | 1.5 Mbps | 750 Kbps | 40 |
| Regular 4G/LTE | 4 Mbps | 3 Mbps | 20 |
| DSL | 2 Mbps | 1 Mbps | 5 |
| Wi-Fi | 30 Mbps | 15 Mbps | 2 |

Network Timings
---------------

Also, on the network tab, you can see how long each request took to complete. We can look at how long a 267.5Kb SVG image asset took to download.

![The time it took for a large SVG asset to load.](/en-US/docs/Web/Performance/Understanding_latency/latencymlw.png)

When a request is in a queue, waiting for a network connection it is considered **blocked**. Blocking happens when there are too many simultaneous connections made to a single server over HTTP. If all connections are in use, the browser can't download more resources until a connection is released, meaning those requests and resources are blocked.

**DNS resolution** is the time it took to do the DNS lookup. The greater the number of hostnames, the more DNS lookups need to be done.

**Connecting** is the time it takes for a TCP handshake to complete. Like DNS, the greater the number of server connections needed, the more time is spent creating server connections.

The **TLS handshake** is how long it took to set up a secure connection. While a TLS handshake does take longer to connect than an insecure connection, the additional time needed for a secure connection is worth it.

**Sending** is the time taken to send the HTTP request to the server.

**Waiting** is disk latency, the time it took for the server to complete its response. Disk latency used to be the main area of performance concern. However, server performance has improved as computer memory, or CPU, has improved. Depending on the complexity of what is needed from the server, this can still be an issue.

**Receiving** is the time it takes to download the asset. The receiving time is determined by a combination of the network capacity and the asset file size. If the image been cached, this would have been nearly instantaneous. Had we throttled, receiving could have been 43 seconds!

Measuring latency
-----------------

**Network latency** is the time it takes for a data request to get from the computer making the request, to the computer responding. Including the time it takes for a byte of data to make it from the responding computer back to the requesting computer. It is generally measured as a round trip delay.

**Disk latency** is the time it takes from the moment a computer, usually a server, receives a request, to the time the computer returns the response.


Animation performance and frame rate - Web performance

Animation performance and frame rate
====================================

Animation on the web can be done via `SVG`, `JavaScript`, including `<canvas>` and `WebGL`, CSS `animation`, `<video>`, animated gifs and even animated PNGs and other image types. The performance cost of animating a CSS property can vary from one property to another, and animating expensive CSS properties can result in jank as the browser struggles to hit a smooth frame rate.

For animated media, such as video and animated gifs, the main performance concern is file size - downloading the file fast enough to not negatively impact performance is the greatest issue. Code based animations, be it CSS, SVG, <canvas>, webGL or other JavaScript animations, can cause performance issues even if the bandwidth footprint is small. These animations can consume CPU and/or cause jank.

Users expect all interface interactions to be smooth and all user interfaces to be responsive. Animation can help make a site feel faster and responsive, but animations can also make a site feel slower and janky if not done correctly. Responsive user interfaces have a frame rate of 60 frames per second (fps). While it is not always possible to maintain 60fps, it is important to maintain a high and steady frame rate for all animations.

With CSS animations you specify a number of keyframes, each of which uses CSS to define the appearance of the element at a particular stage of the animation. The browser creates the animation as a transition from each keyframe to the next.

Compared with animating elements using JavaScript, CSS animations can be easier to create. They can also give better performance, as they give the browser more control over when to render frames, and to drop frames if necessary.

However, the performance cost of modifying a CSS property can vary from one property to another. It's commonly accepted that 60 frames per second is the rate at which animations will appear smooth. For a rate of 60 frames per second, the browser has 16.7 milliseconds to execute scripts, recalculate styles and layout if needed, and repaint the area being updated. Slow scripts and animating expensive CSS properties can result in jank as the browser struggles to hit a smooth frame rate.

The rendering waterfall
-----------------------

The process a browser uses to paint changes to a page when an element is animating CSS properties can be described as a waterfall consisting of the following steps:

![Flowchart of the CSS rendering waterfall. In order, the steps are recalculate style, layout, and paint.](/en-US/docs/Web/Performance/Animation_performance_and_frame_rate/css-rendering-waterfall.png)

1. **Recalculate Style**: when a property for an element changes, the browser must recalculate computed styles.
2. **Layout**: next, the browser uses the computed styles to figure out the position and geometry for the elements. This operation is labeled "layout" but is also sometimes called "reflow".
3. **Paint**: finally, the browser needs to repaint the elements to the screen. One last step is not shown in this sequence: the page may be split into layers, which are painted independently and then combined in a process called "Composition".

This sequence needs to fit into a single frame, since the screen isn't updated until it is complete.

CSS property cost
-----------------

In the context of the rendering waterfall, some properties are more expensive than others:

* Properties that affect an element's **geometry** or **position** trigger a:
    + style recalculation
    + layout
    + repaintFor example: `left`, `max-width`, `border-width`, `margin-left`, `font-size`
* Properties that do *not* affect geometry or position and are *not rendered* in their own layer, do *not* trigger a layout. They do trigger a:
    + style recalculation
    + repaintFor example: `color`
* Properties that *are rendered* in their **own layer** don't even trigger a repaint, because the update is handled in **composition**. These do trigger:
    + style recalculationFor example: `transform`, `opacity`
Developer tools
---------------

Most web browsers include tools to provide insight into the work the browser is doing when it animates elements of a page. Using these tools you can measure an application's animation frame rate, and diagnose performance bottlenecks if any are found.

* Chrome performance tools
* Firefox performance tools


XML introduction - XML: Extensible Markup Language

XML introduction
================

XML (Extensible Markup Language) is a markup language similar to HTML, but without predefined tags to use. Instead, you define your own tags designed specifically for your needs. This is a powerful way to store data in a format that can be stored, searched, and shared. Most importantly, since the fundamental format of XML is standardized, if you share or transmit XML across systems or platforms, either locally or over the internet, the recipient can still parse the data due to the standardized XML syntax.

There are many languages based on XML, including XHTML, MathML, SVG, RSS, and RDF. You can also define your own.

Structure of an XML document
----------------------------

The whole structure of XML and XML-based languages is built on tags.

### XML declaration

XML - declaration is not a tag. It is used for the transmission of the meta-data of a document.

```html
<?xml version="1.0" encoding="UTF-8"?>
```

#### Attributes

`version`

Used version XML in this document.

`encoding`

Used encoding in this document.

### Comments

```html
<!-- Comment -->
```

"Correct" XML (valid and well-formed)
-------------------------------------

### Correct design rules

For an XML document to be correct, the following conditions must be fulfilled:

* Document must be well-formed.
* Document must conform to all XML syntax rules.
* Document must conform to semantic rules, which are usually set in an XML schema or a DTD (**Document Type Definition)**.
### Example

```xml
<?xml version="1.0" encoding="UTF-8"?>
<message>
    <warning>
        Hello World
    <!--missing </warning> -->
</message>
```

Now let's look at a corrected version of that same document:

```xml
<?xml version="1.0" encoding="UTF-8"?>
<message>
    <warning>
         Hello World
    </warning>
</message>
```

A document that contains an undefined tag is invalid. For example, if we never defined the `<warning>` tag, the document above wouldn't be valid.

Most browsers offer a debugger that can identify poorly-formed XML documents.

Entities
--------

Like HTML, XML offers methods (called entities) for referring to some special reserved characters (such as a greater than sign which is used for tags). There are five of these characters that you should know:

| Entity | Character | Description |
| --- | --- | --- |
| < | < | Less than sign |
| > | > | Greater than sign |
| & | & | Ampersand |
| " | " | One double-quotation mark |
| ' | ' | One apostrophe (or single-quotation mark) |

Even though there are only 5 declared entities, more can be added using the document's Document Type Definition. For example, to create a new `&warning;` entity, you can do this:

```xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE body [
 <!ENTITY warning "Warning: Something bad happened... please refresh and try again.">
]>
<body>
  <message> &warning; </message>
</body>
```

You can also use numeric character references to specify special characters; for example, © is the "©" symbol.

Displaying XML
--------------

XML is usually used for descriptive purposes, but there are ways to display XML data. If you don't define a specific way for the XML to be rendered, the raw XML is displayed in the browser.

One way to style XML output is to specify CSS to apply to the document using the `xml-stylesheet` processing instruction.

```xml
<?xml-stylesheet type="text/css" href="stylesheet.css"?>
```

There is also another more powerful way to display XML: the **Extensible Stylesheet Language Transformations** (XSLT) which can be used to transform XML into other languages such as HTML. This makes XML incredibly versatile.

```xml
<?xml-stylesheet type="text/xsl" href="transform.xsl"?>
```

Recommendations
---------------

This article is obviously only a very brief introduction to what XML is, with a few small examples and references to get you started. For more details about XML, you should look around on the Web for more in-depth articles.

Learning the HyperText Markup Language (HTML) will help you better understand XML.

See also
--------

* XML.com
* Extensible Markup Language (XML) @ W3.org
* Using XML: A List Apart


Parsing and serializing XML - XML: Extensible Markup Language

Parsing and serializing XML
===========================

At times, you may need to parse XML content and convert it into a DOM tree, or, conversely, serialize an existing DOM tree into XML. In this article, we'll look at the objects provided by the web platform to make the common tasks of serializing and parsing XML easy.

`XMLSerializer`

Serializes DOM trees, converting them into strings containing XML.

`DOMParser`

Constructs a DOM tree by parsing a string containing XML, returning a `XMLDocument` or `Document` as appropriate based on the input data.

`fetch()`

Loads content from a URL. XML content is returned as a text string which you can parse using `DOMParser`.

`XMLHttpRequest`

The precursor to `fetch()`. Unlike the `fetch()` API, `XMLHttpRequest` can return a resource as a `Document`, via its `responseXML` property.

XPath

A technology for creating strings that contain addresses for specific portions of an XML document, and locating XML nodes based on those addresses.

Creating an XML document
------------------------

Using one of the following approaches to create an XML document (which is an instance of `Document`).

### Parsing strings into DOM trees

This example converts an XML fragment in a string into a DOM tree using a `DOMParser`:

```js
const xmlStr = '<q id="a"><span id="b">hey!</span></q>';
const parser = new DOMParser();
const doc = parser.parseFromString(xmlStr, "application/xml");
// print the name of the root element or error message
const errorNode = doc.querySelector("parsererror");
if (errorNode) {
  console.log("error while parsing");
} else {
  console.log(doc.documentElement.nodeName);
}
```

### Parsing URL-addressable resources into DOM trees

#### Using XMLHttpRequest

Here is sample code that reads and parses a URL-addressable XML file into a DOM tree:

```js
fetch("example.xml")
  .then((response) => response.text())
  .then((text) => {
    const parser = new DOMParser();
    const doc = parser.parseFromString(text, "text/xml");
    console.log(doc.documentElement.nodeName);
  });
```

This code fetches the resource as a text string, then uses `DOMParser.parseFromString()` to construct an `XMLDocument`.

If the document is HTML, the code shown above will return a `Document`. If the document is XML, the resulting object is actually an `XMLDocument`. The two types are essentially the same; the difference is largely historical, although differentiating has some practical benefits as well.

**Note:** There is in fact an `HTMLDocument` interface as well, but it is not necessarily an independent type. In some browsers it is, while in others it is an alias for the `Document` interface.

Serializing an XML document
---------------------------

Given a `Document`, you can serialize the document's DOM tree back into XML using the `XMLSerializer.serializeToString()` method.

Use the following approaches to serialize the contents of the XML document you created in the previous section.

### Serializing DOM trees to strings

First, create a DOM tree as described in How to Create a DOM tree. Alternatively, use a DOM tree obtained from `fetch()`.

To serialize the DOM tree `doc` into XML text, call `XMLSerializer.serializeToString()`:

```js
const serializer = new XMLSerializer();
const xmlStr = serializer.serializeToString(doc);
```

### Serializing HTML documents

If the DOM you have is an HTML document, you can serialize using `serializeToString()`, but there is a simpler option: just use the `Element.innerHTML` property (if you want just the descendants of the specified node) or the `Element.outerHTML` property if you want the node and all its descendants.

```js
const docInnerHtml = document.documentElement.innerHTML;
```

As a result, `docInnerHtml` is a string containing the HTML of the contents of the document; that is, the `<body>` element's contents.

You can get HTML corresponding to the `<body>` *and* its descendants with this code:

```js
const docOuterHtml = document.documentElement.outerHTML;
```

See also
--------

* XPath
* `fetch()`
* `XMLHttpRequest`
* `Document`, `XMLDocument`, and `HTMLDocument`


Common (exsl) - EXSLT

Common (exsl)
=============

**XSLT/XPath Reference**: XSLT elements, EXSLT functions, XPath functions, XPath axes

The EXSLT Common package provides basic functions that expand upon the capabilities of XSLT. The namespace for the Common package is `http://exslt.org/common`.

exsl:node-set()`exsl:node-set()` returns a node-set from a result tree fragment, which is what you get when you look at the `xsl:variable` instead of its select attribute to fetch a variable's value. This lets you process the XML created within a variable to process it in multiple steps.

exsl:object-type()`exsl:object-type()` returns a string that indicates the type of the specified object.


Math (math) - EXSLT

Math (math)
===========

**XSLT/XPath Reference**: XSLT elements, EXSLT functions, XPath functions, XPath axes

The EXSLT Math package provides functions for working with numeric values and comparing nodes. The namespace for the Math package is `http://exslt.org/math`.

math:highest()`math:highest()` returns the node in the specified node-set with the highest value (where the highest value calculated using `math:max()`).

math:lowest()`math:lowest()` returns the node in the specified node-set with the lowest value (where the lowest value calculated using `math:min()`).

math:max()`math:max()` returns the maximum value of a node-set.

math:min()`math:min()` returns the minimum value of a node-set.


Strings (str) - EXSLT

Strings (str)
=============

**XSLT/XPath Reference**: XSLT elements, EXSLT functions, XPath functions, XPath axes

The EXSLT Strings package provides functions that allow the manipulation of strings. The namespace for the Strings package is `http://exslt.org/strings`.

str:concat()`str:concat()` returns a string containing all the string values in a node-set concatenated together.

str:split()`str:split()` splits a string using a pattern string to determine where the splits should occur, returning a node-set containing the resulting strings.

str:tokenize()`str:tokenize()` splits a string using a set of characters as delimiters that determine where the splits should occur, returning a node-set containing the resulting strings.


Sets (set) - EXSLT

Sets (set)
==========

**XSLT/XPath Reference**: XSLT elements, EXSLT functions, XPath functions, XPath axes

The EXSLT Sets package offers functions that let you perform set manipulation. The namespace for these functions is `http://exslt.org/sets`.

set:difference()`set:difference()` returns the difference between two node-sets. In other words, it returns a node-set whose nodes are in one node-set but not in the other.

set:distinct()`set:distinct()` returns a subset of the nodes in the specified node-set, returning only nodes with unique string values.

set:has-same-node()`set:has-same-node()` determines whether two node-sets have any nodes in common.

set:intersection()`set:intersection()` returns the intersection of two node-sets. In other words, it returns a node-set containing all the nodes that exist in both `nodeSet1` and `nodeSet2`.

set:leading()`set:leading()` returns the nodes in one node-set that come before the first node in the other node-set.

set:trailing()`set:trailing()` returns the nodes in one node-set that come after the first node in the other node-set.


Regular expressions (regexp) - EXSLT

Regular expressions (regexp)
============================

**XSLT/XPath Reference**: XSLT elements, EXSLT functions, XPath functions, XPath axes

The EXSLT Regular Expressions package provides functions that allow testing, matching, and replacing text using JavaScript style regular expressions. The namespace for the Regular Expressions package is `http://exslt.org/regular-expressions`.

regexp:match()`regexp:match()` performs regular expression matching on a string, returning the submatches found as a result.

regexp:replace()`regexp:replace()` replaces the portions of a string that match a given regular expression with the contents of another string.

regexp:test()`regexp:test()` tests to see whether a string matches a specified regular expression.


set:distinct() - EXSLT

set:distinct()
==============

**XSLT/XPath Reference**: XSLT elements, EXSLT functions, XPath functions, XPath axes

`set:distinct()` returns a subset of the nodes in the specified node-set, returning only nodes with unique string values.

Syntax
------
```

set:distinct(nodeSet)
```

### Parameters

`nodeSet`

The node-set in which to find unique nodes.

### Returns

A node-set containing the nodes that have unique string values.

Specifications
--------------

EXSLT - SET:DISTINCT


set:trailing() - EXSLT

set:trailing()
==============

**XSLT/XPath Reference**: XSLT elements, EXSLT functions, XPath functions, XPath axes

`set:trailing()` returns the nodes in one node-set that come after the first node in the other node-set.

Syntax
------
```

set:trailing(nodeSet1, nodeSet2)
```

### Parameters

`nodeSet1`

The node set to find nodes in that follow the first node in the second node set.

`nodeSet2`

The node set to compare against.

### Returns

A node-set containing the nodes from `nodeSet1` whose values follow the first node in `nodeSet2`.

**Note:** If the first node in `nodeSet2` isn't contained in `nodeSet1`, an empty set is returned. If `nodeSet2` is empty, then the result is `nodeSet1`.

Specifications
--------------

EXSLT - SET:TRAILING


set:leading() - EXSLT

set:leading()
=============

**XSLT/XPath Reference**: XSLT elements, EXSLT functions, XPath functions, XPath axes

`set:leading()` returns the nodes in one node-set that come before the first node in the other node-set.

Syntax
------

```js
set:leading(nodeSet1, nodeSet2)
```

### Parameters

`nodeSet1`

The node set to find nodes in that precede the first node in the second node set.

`nodeSet2`

The node set to compare against.

### Returns

A node-set containing the nodes from `nodeSet1` whose values precede the first node in `nodeSet2`.

**Note:** If the first node in `nodeSet2` isn't contained in `nodeSet1`, an empty set is returned. If `nodeSet2` is empty, then the result is `nodeSet1`.

Specifications
--------------

EXSLT - SET:LEADING


set:intersection() - EXSLT

set:intersection()
==================

**XSLT/XPath Reference**: XSLT elements, EXSLT functions, XPath functions, XPath axes

`set:intersection()` returns the intersection of two node-sets. In other words, it returns a node-set containing all the nodes that exist in both `nodeSet1` and `nodeSet2`.

Syntax
------
```

set:intersection(nodeSet1, nodeSet2)
```

### Arguments

`nodeSet1`

The first node-set.

`nodeSet2`

The second node-set.

### Returns

A node-set containing the nodes that existed in both `nodeSet1` and in `nodeSet2`.

Specifications
--------------

EXSLT - SET:INTERSECTION


set:difference() - EXSLT

set:difference()
================

**XSLT/XPath Reference**: XSLT elements, EXSLT functions, XPath functions, XPath axes

`set:difference()` returns the difference between two node-sets. In other words, it returns a node-set whose nodes are in one node-set but not in the other.

The template version of `set:difference` applies templates to these nodes in `set:difference` mode, copying the nodes so that a result tree fragment consisting of the nodes is returned.

Syntax
------
```

set:difference(nodeSet1, nodeSet2)
```

### Parameters

`nodeSet1`

The node-set from which to subtract nodes.

`nodeSet2`

The set of nodes to subtract from `nodeSet1`.

### Returns

A node-set containing the nodes that are in `nodeSet1` but not in `nodeSet2`.

Specifications
--------------

EXSLT - SET:DIFFERENCE


set:has-same-node() - EXSLT

set:has-same-node()
===================

**XSLT/XPath Reference**: XSLT elements, EXSLT functions, XPath functions, XPath axes

`set:has-same-node()` determines whether two node-sets have any nodes in common.

Syntax
------
```

set:has-same-node(nodeSet1, nodeSet2)
```

### Parameters

`nodeSet1`

The first node set to check.

`nodeSet2`

The second node set to check.

### Returns

`true` if the two node-sets have any nodes in common; otherwise `false`.

Specifications
--------------

EXSLT - SET:HAS-SAME-NODE


regexp:match() - EXSLT

regexp:match()
==============

**XSLT/XPath Reference**: XSLT elements, EXSLT functions, XPath functions, XPath axes

`regexp:match()` performs regular expression matching on a string, returning the submatches found as a result.

Syntax
------

```js
regexp:match(targetString, regExpString[, flagsString])
```

### Parameters

`targetString`

The string to perform regular expression matching upon.

`regExpString`

The JavaScript style regular expression to evaluate.

`flagsString` Optional

An optional string containing character flags.

The character flags are:

`g`

Global match. The submatches from every match in the string are returned. If this flag isn't specified, only the submatches from the first match are returned.

`i`

Case insensitive match. If this flag is specified, the match is performed in a case insensitive fashion.

### Returns

A node set of `match` elements, each of which has the string value equal to a portion of the first parameter string as captured by the regular expression. If the match isn't a global one, the first match element has the value of the portion of the string matched by the entire regular expression.

For example:

```xml
<xsl:for-each select="regExp:match('https://developer.mozilla.org/en/docs/Firefox\_3\_for\_developers',
 '(\w+):\/\/([^/:]+)(:\d\*)?([^# ]\*)')">
   Part <xsl:value-of select="position()" /> = <xsl:value-of select="." />
</xsl:for-each>
```

This code generates the following output:
```

Part 1 = https://developer.mozilla.org/en/docs/Firefox_3_for_developers
Part 2 = https
Part 3 = developer.mozilla.org
Part 4 =
Part 5 = /en/docs/Firefox_3_for_developers
```

Specifications
--------------

EXSLT - REGEXP:MATCH


regexp:replace() - EXSLT

regexp:replace()
================

**XSLT/XPath Reference**: XSLT elements, EXSLT functions, XPath functions, XPath axes

`regexp:replace()` replaces the portions of a string that match a given regular expression with the contents of another string.

Syntax
------
```

regexp:replace(originalString, regExpString, flagsString, replaceString)
```

### Parameters

`originalString`

The string perform a search-and-replace operation upon.

`regExpString`

The JavaScript style regular expression to evaluate.

`flagsString`

The string containing character flags.

`replaceString`

The string with which the matched substrings are to be replaced.

The character flags are:

`g` - Global replace

If this flag is specified, all occurrences of the regular expression within the `originalString` are replaced. Otherwise only the first occurrence is replaced.

`i` - Case insensitive match

If this flag is specified, the match is performed in a case insensitive fashion.

### Returns

The revised version of the string.

Specifications
--------------

EXSLT - REGEXP:REPLACE


regexp:test() - EXSLT

regexp:test()
=============

**XSLT/XPath Reference**: XSLT elements, EXSLT functions, XPath functions, XPath axes

`regexp:test()` tests to see whether a string matches a specified regular expression.

Syntax
------

```js
regexp:test(testString, regExpString[, flagsString])
```

### Parameters

`testString`

The string to test.

`regExpString`

The JavaScript style regular expression to evaluate.

`flagsString` Optional

An optional string containing character flags.

The character flags are:

`g`

Global match. Has no effect for this function; it's allowed for consistency with other regexp functions.

`i`

Case insensitive match<. If this flag is specified, the match is performed in a case insensitive fashion.

### Returns

`true` if the specified regexp matches the test string.

Specifications
--------------

EXSLT - REGEXP:TEST


exsl:node-set() - EXSLT

exsl:node-set()
===============

**XSLT/XPath Reference**: XSLT elements, EXSLT functions, XPath functions, XPath axes

`exsl:node-set()` returns a node-set from a result tree fragment, which is what you get when you look at the `xsl:variable` instead of its select attribute to fetch a variable's value. This lets you process the XML created within a variable to process it in multiple steps.

You can also use `exsl:node-set()` to turn strings into text nodes.

Syntax
------
```

exsl:node-set(object)
```

### Parameters

`object`

The object for which to return the corresponding node-set.

### Returns

The node-set corresponding to the specified `object`.

Specifications
--------------

EXSLT - EXSL:NODE-SET


exsl:object-type() - EXSLT

exsl:object-type()
==================

**XSLT/XPath Reference**: XSLT elements, EXSLT functions, XPath functions, XPath axes

`exsl:object-type()` returns a string that indicates the type of the specified object.

**Note:** Most XSLT object types can be coerced into each other safely; however, certain coercions to raise error conditions. In particular, treating something that's not a node-set as a node-set will do so. This function lets authors of named templates and extension functions easily provide flexibility in parameter values.

Syntax
------
```

exsl:object-type(object)
```

### Parameters

`object`

The object whose type is to be returned.

### Returns

The object's type, which will be one of the following:

* `string`
* `number`
* `boolean`
* `node-set`
* `RTF`
* `external`
Specifications
--------------

EXSLT - EXSL:OBJECT-TYPE


str:concat() - EXSLT

str:concat()
============

**XSLT/XPath Reference**: XSLT elements, EXSLT functions, XPath functions, XPath axes

`str:concat()` returns a string containing all the string values in a node-set concatenated together.

Syntax
------
```

str:concat(nodeSet)
```

### Parameters

`nodeSet`

The node-set whose nodes' string values should be concatenated into one string.

### Returns

A string whose value is all the string values of the nodes in `nodeSet` concatenated together. If `nodeSet` is empty, an empty string is returned.

Specifications
--------------

EXSLT - STR:CONCAT