# "Network dependency tree": how to fix it in Lighthouse

**Audit ID:** `network-dependency-tree-insight` · **Category:** Performance

<!--QA-->
> **Quick answer:** The Network dependency tree insight shows chains of critical requests, such as HTML to CSS to a web font, where each file is found only after the previous one loads. Lighthouse 13 replaced "avoid chaining critical requests" with it. Fix it by shortening the longest chain: preload fonts, avoid CSS @import, inline critical CSS, and defer non-critical scripts.
<!--/QA-->

This insight shows the chains of critical requests the browser loads one after another, where each file is found only after the previous one loads. The HTML document starts every chain. A stylesheet the HTML references is one level down. A web font that stylesheet references is one level further. Each level adds a full network round trip before the next request can even start. Lighthouse 13 shows this as the **Network dependency tree** insight, and its description still uses the older wording, "Avoid chaining critical requests". In our study of 269 Shopify storefronts, 252 of them (93.7%) failed it. This page covers what the tree shows, which chain to fix first, and the fixes that remove a level from the chain.

## TL;DR

- **What:** A list of critical request chains, with the longest chain and its latency at the top, plus two tables: the origins you already preconnect to, and origins that would benefit from a preconnect.
- **Why it matters:** Each level adds a round trip on a throttled mobile connection. When the chain runs through render-blocking stylesheets or scripts, nothing paints until those finish, so the delay lands on [First Contentful Paint](/audits/first-contentful-paint). When the chain ends in a high-priority file that does not block rendering, such as the LCP image or a font, the page can paint first and the delay lands on [Largest Contentful Paint](/audits/largest-contentful-paint).
- **Fix:** Remove a level from the longest chain. Preload the font or LCP image from the HTML, replace CSS `@import` with `<link>`, inline critical CSS, add `defer` to scripts, and keep `preconnect` hints to the one to four origins on that chain.

## What does "Network dependency tree" mean?

A **critical request** is one the browser treats as render-blocking or high priority: the HTML document, stylesheets, synchronous scripts in the `<head>`, web fonts, and anything you preload. Not every critical request blocks rendering. The page can paint while a high-priority image or font is still loading. A **chain** forms when one critical request can only be discovered after another finishes. The browser cannot request a font until it has parsed the stylesheet that names it, and it cannot request that stylesheet until it has parsed the HTML.

```text
https://www.example.com/                      (HTML, 102 KB, 106 ms)
└── https://cdn.example.com/theme.css         (CSS, 48 KB, 410 ms)
    └── https://cdn.example.com/fonts/brand.woff2   (font, 61 KB, 1,250 ms)
```

Lighthouse builds this tree from the page load trace and reports:

| Part of the report | What it tells you |
|---|---|
| **Maximum critical path latency** | The time from navigation start to the end of the slowest chain. This is the number to lower. |
| **The tree** | Every critical chain, nested. The longest chain is marked. Each row shows the URL, its transfer size, and when it finished. |
| **Preconnected origins** | The `<link rel="preconnect">` hints Lighthouse found in your HTML, with the element that set each one. More than four triggers a warning. |
| **Preconnect candidates** | Third-party origins on the critical path with no preconnect hint, and the estimated time a hint would save. "No additional origins are good candidates" means there is nothing to add. |

Lighthouse 13 retired the old `critical-request-chains` audit. The same analysis now lives in this insight, so a guide that tells you to fix "Avoid chaining critical requests" is talking about this section.

The insight carries no weight in the Performance score. It explains the score through the metrics: a chain through render-blocking files delays first paint, and a chain that ends in the LCP image or a font delays the largest paint. That lowers FCP, LCP, and [Speed Index](/audits/speed-index), and those metrics carry the weight.

## Why does almost every page fail this insight?

Because almost every page has at least one chain. External CSS plus a web font is already a two-level chain, and Lighthouse lists it. A fail here is not a bug in your page. The question is how long the longest chain is and how many levels it has. Read the maximum critical path latency first. On a throttled mobile run, under about 1 second is fine for most pages; several seconds means a level of the chain is waiting on something slow, usually a font or a script-injected stylesheet.

## How do I find the chain to fix?

1. **In the Lighthouse report,** open the Performance section and expand **Network dependency tree**. Note the maximum critical path latency and follow the chain marked as longest down to its last request.
2. **Read the last request in the longest chain.** That is the resource that finished last. A font, an image fetched from CSS, or a second stylesheet pulled in by `@import` are the usual endings.
3. **Read the level above it.** That request is why the browser discovered the last one late. The fix is nearly always to make the last request discoverable earlier, or to remove the level above it.
4. **Sort by ownership.** A chain that starts with a URL on your domain or theme assets folder is yours. A chain that starts with a vendor tag belongs to the vendor.
5. **In DevTools,** the Performance panel's Insights sidebar shows the same tree after a recording. The Network panel's **Initiator** column shows which request discovered each one, which is the chain in table form.

## How do I shorten a critical request chain?

### 1. Preload what the browser discovers late

A font named in CSS is discovered only after the CSS arrives. A preload in the HTML lets the browser request it at the same time as the stylesheet, which removes one level.

```html
<link rel="preload" href="/fonts/brand.woff2" as="font" type="font/woff2" crossorigin>
```

Do the same for the LCP image when CSS sets it as a background, or when a script inserts it. Preload only the one or two files on the longest chain. Every preload competes for bandwidth with the HTML and CSS.

### 2. Replace `@import` with `<link>`

Each `@import` inside a stylesheet is a new level: the browser must download and parse the first file before it sees the second. Move every `@import` to a `<link rel="stylesheet">` in the HTML, so all stylesheets download in parallel.

```css
/* theme.css: adds a level to the chain */
@import url("https://fonts.googleapis.com/css2?family=Inter&display=swap");
```

```html
<!-- HTML: discovered immediately, downloaded in parallel -->
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Inter&display=swap">
```

### 3. Inline the critical CSS

The CSS the first screen needs is usually small. Inline it in a `<style>` block in the `<head>` and load the full stylesheet with lower priority. The browser can paint from the inline CSS without waiting for the external file, so the chain through the stylesheet no longer blocks render. This is the same fix as [Eliminate render-blocking resources](/audits/render-blocking-resources).

### 4. Defer scripts that do not render content

A synchronous `<script>` in the `<head>` is critical, and any stylesheet or font it inserts is a level below it. Add `defer` to scripts that do not produce first-screen content, and `async` to analytics and tags. A script that injects a stylesheet at runtime creates a chain the browser could not see from the HTML; move that stylesheet into a `<link>` tag instead.

### 5. Preconnect to the origins on the chain, and only those

A `<link rel="preconnect">` opens the DNS, TCP, and TLS handshake early, which saves a round trip on the first request to that origin. Use it for the one to four third-party origins that appear in the longest chain, such as a font host or your CDN.

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

Remove the rest. Each preconnect costs CPU and a socket, and Lighthouse warns when it finds more than four: "More than 4 `preconnect` connections were found. These should be used sparingly and only to the most important origins." The **Preconnect candidates** table tells you which origins would benefit; if it says there are no candidates, add none.

### 6. Make each level smaller

When you cannot remove a level, shrink it. Subset fonts to the characters you use, serve WOFF2, compress CSS and scripts ([Enable text compression](/audits/enable-text-compression)), and drop CSS the page never uses ([Reduce unused CSS](/audits/reduce-unused-css)). A smaller file finishes sooner, and the next level starts sooner.

## How do I fix the Network dependency tree in Shopify, WordPress, or a JavaScript framework?

- **Shopify:** the usual chain is the theme's `theme.css` to a font on `fonts.shopifycdn.com`, plus app embeds that inject their own stylesheets. Preload the primary font in `theme.liquid`, keep the theme's `preconnect` tags for `cdn.shopify.com` and the font host only, and move app embeds you need to load after `window.load`. App scripts that inject CSS are the vendor's chain.
- **WordPress:** page builders and plugins each add stylesheets, and themes often use `@import` for Google Fonts. Self-host the font and preload it, replace `@import` with `wp_enqueue_style`, and use a critical CSS feature in your caching plugin to inline the first-screen styles. Disable plugin stylesheets on pages that do not use the plugin.
- **React, Next.js, and other frameworks:** a dynamic import on the critical path creates a chain of chunks. Keep the first-screen component in the main bundle, use the framework's font loader so fonts are preloaded from the HTML, and avoid loading CSS through JavaScript for the first screen.

## Can I fix a chain that starts with a third-party script?

You cannot edit vendor code. A chat widget that loads a script, which loads a stylesheet, which loads a font, is a three-level chain you did not write. Your options:

1. **Load it later.** Start the widget after `window.load` or on first interaction. The chain still exists, but it no longer sits on the critical path.
2. **Preconnect to its origin** if it must load early. This removes the handshake from the first level.
3. **Update the SDK.** Vendors shorten their load sequence in new versions.
4. **Remove the tag** if it does not earn its place. This is the only fix you fully control.

## How do I verify the fix?

1. Re-run Lighthouse. The maximum critical path latency should be lower, and the longest chain should have one level fewer.
2. Check the **Preconnected origins** table. The warning about more than four preconnects should be gone.
3. Open the Network panel in DevTools with the Initiator column visible. The font or image you preloaded should now show the HTML document as its initiator.
4. Watch [First Contentful Paint](/audits/first-contentful-paint) and [Largest Contentful Paint](/audits/largest-contentful-paint). Those are the metrics the chain was delaying.

## What mistakes should I avoid?

- **Preloading everything.** Ten preloads compete with the HTML and CSS for bandwidth, and the chain gets longer, not shorter. Preload the one or two files that end the longest chain.
- **Adding a preconnect for every third party.** Past four, Lighthouse warns, and each one costs a socket the critical request could have used.
- **Treating the fail as a bug.** Nearly every page lists a chain. Fix the number, the maximum critical path latency, not the existence of the tree.
- **Chasing a vendor chain you cannot change.** Decide whether to keep the tag. Rewriting your own CSS does not shorten their chain.

## Related audits

- [Eliminate render-blocking resources](/audits/render-blocking-resources): the stylesheets and scripts at the top of most chains
- [Ensure text remains visible during webfont load](/audits/font-display): the font at the end of most chains
- [Largest Contentful Paint](/audits/largest-contentful-paint): the metric a long chain delays most
- [Reduce unused CSS](/audits/reduce-unused-css): makes the stylesheet level of the chain smaller

---

Audit your URL at https://lighthouse-md.com.
