Skip to content

network-priority/waterfall-inspector

Repository files navigation

Waterfall Inspector

A Manifest V3 browser extension that visualises a page's network request waterfall, annotates every resource with its computed / estimated fetch priority, and highlights the loading problems that hurt real-world performance — render-blocking resources and late-discovered critical assets.

No build step, no npm dependencies, no telemetry. Just load it unpacked.


What it does

Waterfall Inspector gives you two ways to inspect how a page loads:

  1. A DevTools panel ("Waterfall") that draws the full request timeline from the browser's own network data, with per-phase timing bars and a priority badge on every row.
  2. An in-page overlay — a compact, draggable panel injected into the current tab straight from the toolbar popup, so you can spot problems without even opening DevTools.

Both surfaces label priority clearly as estimated wherever the browser's real internal value is not available to them, and both flag the same classes of issue.

Screenshots / What you see

DevTools panel (the "Waterfall" tab). A toolbar with a URL filter, a resource-type filter, a sort control (by start time, priority, size or duration), a Copy report button and Clear. Below it: a row of summary stats (requests, transferred bytes, render-blocking count, third-party origins, largest and slowest resource), a findings area, then the request table. Each row shows the file name, type, a colour-coded priority badge, size, total time, and a segmented waterfall bar (blocked, DNS, connect, TLS, TTFB, download). Render-blocking rows carry a deep-red edge; late-discovered critical rows carry a copper edge. A legend maps each colour to a timing phase.

In-page overlay. A small olive/gold panel pinned to the top-right of the page. A draggable header (with collapse and close buttons), four summary chips, a findings list, and a scrollable set of rows — each with a name, an estimated priority badge, transferred size, and a mini waterfall bar. It lives inside a Shadow DOM, so the host page's CSS can neither style it nor be styled by it.

Install (load unpacked)

This extension is distributed as source you load yourself.

Chrome / Edge / Brave (and other Chromium browsers):

  1. Open the extensions page: type chrome://extensions (or edge://extensions) into the address bar and press Enter.
  2. Turn on Developer mode (toggle in the top-right corner).
  3. Click Load unpacked.
  4. Select this project's waterfall-inspector folder (the one containing manifest.json).
  5. Pin the extension from the puzzle-piece toolbar menu if you want quick access.

To see the DevTools panel, open DevTools (F12, or Cmd+Opt+I on macOS) on any page and choose the Waterfall tab. Reload the page to capture its waterfall.

Firefox: Firefox supports MV3 but uses browser.* APIs and a slightly different DevTools model. This build targets Chromium. To try it in Firefox, load it as a temporary add-on from the debugging page (about:debugging), and expect the DevTools panel behaviour to differ; the popup and overlay rely on the chrome.* namespace that Firefox aliases but does not fully match for devtools.panels. Chromium browsers are the supported target.

How the estimated priority is computed

The browser's real internal scheduling priority is not exposed to page JavaScript. So the overlay (and the DevTools panel, when the browser value is missing) estimates it from documented signals: the resource's initiator / element type, whether it is render-blocking, its fetchpriority attribute, a preload's as, loading="lazy", and whether it looks like the Largest Contentful Paint candidate.

In the DevTools panel, when the browser reports a priority in the HAR data (_priority), that value is used directly and the row is not marked as estimated.

The heuristic mirrors Blink's rough defaults:

Resource (initiatorType / element) Estimated priority
Main document / navigation Highest
CSS <link rel=stylesheet> in <head> (render-blocking) Highest
CSS that is non-blocking, media-scoped or loaded late Medium
Font (as=font, .woff2, CSS-loaded) High
Blocking <script> in <head> (no async/defer) High
<script> with async / defer / injected Low
Image that is the LCP candidate / above the fold High
Image, in-flow default Low
Image with loading="lazy" / offscreen Lowest
XHR / fetch() High
Beacon / ping Lowest
Audio / video Low
Anything else Medium

Then Priority Hints nudge the result: fetchpriority="high" moves it up one step, fetchpriority="low" moves it down one step. The five levels — Highest, High, Medium, Low, Lowest — are colour-coded from clay/copper through gold to moss/sage. The full logic and its inline references live in lib/priority.js.

Features

  • Waterfall bars with distinct colours for each timing phase: blocked/stalled, DNS, connection, TLS, waiting (TTFB) and content download.
  • A colour-coded priority badge per row (Highest / High / Medium / Low / Lowest), with a tooltip explaining why that level was chosen.
  • Highlights render-blocking resources: synchronous <script> in <head> without async/defer, and active non-print <link rel=stylesheet> in <head>.
  • Highlights late-discovered critical assets: CSS, fonts and large images fetched well after the page started — with a suggestion to preload them.
  • Flags lazy-loaded images that are above the fold (an LCP risk).
  • Summary stats: total requests, total transferred bytes, render-blocking count, third-party origin count, largest resource and slowest resource.
  • Sortable and filterable request list (by priority, type, size, time, or a URL substring) in the DevTools panel.
  • A Copy report button that copies a plain-text summary to the clipboard.
  • Draggable, collapsible, dismissable overlay that will not break the host page.

Permissions & privacy

The extension requests the minimum it needs, and only acts on the tab you are looking at when you ask it to:

  • activeTab — grants temporary access to the current tab only after you invoke the extension (open the popup or use its controls). This is what lets the popup read the page's stats and inject the overlay, without a broad host-permission grant.
  • scripting — lets the popup/background inject the overlay and the small stats collector on demand. Nothing is injected until you click a button.
  • web_accessible_resources — exposes only content/overlay.css so the overlay can load its own scoped stylesheet into its Shadow DOM.

There is no host_permissions, no tabs permission for browsing history, and no background network access. The extension reads only local performance data (Resource Timing, HAR entries from your own DevTools session, and the page's DOM) and renders it locally. It sends nothing anywhere — no analytics, no remote logging, no external requests.

How it works

  • DevTools paneldevtools.js registers the "Waterfall" panel; panel.js listens to chrome.devtools.network.onRequestFinished, pulls the HAR entries (including the browser-reported _priority when present), normalises them, runs the analysis and renders the table. It resets when the inspected page navigates.
  • In-page overlay — the popup (popup.js) asks the background service worker (background.js) to inject lib/format.js, lib/priority.js and content/overlay.js into the active tab. The overlay reads performance.getEntriesByType('resource') plus a PerformanceObserver (including a Largest Contentful Paint observer), matches each request to its DOM element to learn fetchpriority / loading / render-blocking status, estimates priorities, and paints itself inside a Shadow DOM. Re-injecting is idempotent — it simply toggles the existing overlay.
  • Shared librarieslib/priority.js (the heuristic), lib/waterfall.js (normalisation + rendering helpers) and lib/format.js (byte/ms formatting) are plain scripts shared by both surfaces.

Limitations

  • Estimated vs. real priority. Outside the DevTools/HAR path, the priority shown is a computed estimate, not the browser's actual internal value, which pages cannot read. Treat it as a well-informed approximation.
  • Cross-origin resources without a Timing-Allow-Origin header expose only coarse timing, so their waterfall bar collapses to a single "download" segment.
  • Render-blocking detection in the DevTools panel is inferred from HAR initiator data (async/defer is not present in HAR), so it is an estimate there too; the overlay reads the live DOM and is more precise.
  • LCP-candidate and above-the-fold checks reflect the page state at the moment the overlay renders.

Further reading

If you want to go deeper on the concepts this tool surfaces:

Contributing

Contributions are welcome. Because there is no build step, the workflow is simple:

  1. Edit the source directly.
  2. Run node --check on any JavaScript file you touch, and confirm manifest.json still parses as valid JSON.
  3. Reload the unpacked extension from the browser's extensions page and verify both the DevTools panel and the overlay.
  4. If you change the icons, regenerate them with node icons/generate-icons.js.

Keep the code vanilla (no dependencies), keep the UI accessible, and keep the priority heuristic documented.

License

Released under the MIT License. Copyright (c) 2026 Network Priority.


Built alongside network-priority.com.

About

Browser extension overlaying the page's request waterfall with computed fetch priorities; flags render-blocking and late-discovered critical assets.

Topics

Resources

License

Stars

0 stars

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors