Skip to lesson

How a page loadsLab

See the chain for yourself.

Change where a script runs and watch what it can see, then measure real page loads in your own browser: the waterfall, an HSTS redirect and every stage's timestamps.

Submodule 1 of 14Free interactive preview

Three experiments. The first runs in this page and shows the order in which the browser parses and runs things.

The other two measure real page loads, which no embedded preview can do. They use and its , which you met in the lesson, and .

What can a script see when it runs?

count.js counts the paragraphs that exist when it runs, and the result explains what happened. Predict the number, run it, then follow the suggestion in the result: add defer to the script tag in index.html and run again, then try async and type="module".

This shows the order of parsing and running, not timing. The preview is a small page inside this page, so it cannot show real DNS, connection or TLS costs; use the DevTools experiment below for those.

index.html
<!doctype html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <title>What can a script see?</title>
    <link rel="stylesheet" href="/styles.css" />
  </head>
  <body>
    <h2>What count.js saw <span id="mode" class="badge"></span></h2>
    <ol id="log"></ol>
    <div class="hint" id="hint"></div>
    <p>First paragraph</p>
    <!-- Try defer, then async, then type="module": <script src="/count.js" defer></script> -->
    <script src="/count.js"></script>
    <p>Second paragraph</p>
    <p>Third paragraph</p>
    <!-- Explains the result; you do not need to change it. -->
    <script src="/explain.js" defer></script>
  </body>
</html>

Edit the code and run it right here. It runs inside this page, with no account and no outside service.

Try it in a real browser

Measure a real page load

Goal: See each wait from this lesson in a real waterfall, find which requests delayed the first paint, and spot a request chain.

Do this

  1. Open a new private window in Chrome and go to a site you have not visited recently. Open DevTools with Cmd + Option + I on macOS or Ctrl + Shift + I on Windows.
  2. Select the Network panel and turn on Disable cache, then reload the page.
  3. Select the first request in the list and open its Timing tab.
  4. Right-click the header of the requests table and turn on the Render-blocking column. Note every request marked blocking.
  5. In the Waterfall column, find the first stylesheet and the first script. Note which ones started only after something else finished.
  6. Press the Font button in the filter bar to list only fonts. Look at the Initiator column of each one: it names the file that asked for it.

What to look for

  • The HTML document is the first request. Its Timing tab shows DNS Lookup and Initial connection (which includes the TLS handshake; DevTools still uses TLS's old name, SSL), then Waiting (TTFB), which covers only the last part: from sending the request to the first byte.
  • If DNS Lookup or Initial connection is missing, the browser reused an earlier answer or connection. Try a site you have not visited.
  • Stylesheets and scripts start only after the HTML has begun to arrive.
  • Requests marked blocking in the Render-blocking column are what the first paint waited for. A plain script in the body may show In-body parser blocking.
  • A font or stylesheet whose Initiator is another stylesheet was found late: it is a link in a request chain.
  • Your numbers will differ from anyone else's.

Record your own numbers. Network, device and browser all change the results, so there is no single correct value.

Try it in a real browser

Watch the upgrade to https:// and time every stage

Goal: See the browser turn http:// into https:// by itself, then read each stage of a page load from Navigation Timing.

Do this

  1. Open a new private window and open DevTools. In the Network panel, turn on Preserve log, so requests stay listed after the page changes.
  2. Type http://github.com into the address bar, with http:// written out, and press Enter. Then try http://www.w3.org the same way.
  3. For each, select the first row and read its status and its Headers tab.
  4. Open the Console panel, paste the Navigation Timing snippet from the lesson and press Enter.
  5. Reload the page, paste the snippet again and compare the two tables.

What to look for

  • The first row is the http:// address with status 307. Its response headers include Non-Authoritative-Reason: Chrome made this redirect itself. HSTS means the site is on the preload list or sent the header before; HttpsUpgrades means Chrome tried https:// on its own.
  • The table from the Console has one row per stage. A 0 means that stage did not happen or was answered from a cache.
  • redirects is 0 even though the Network panel showed a 307: the browser hides redirect timings when the address changes from http:// to https:// or to another name.
  • After a reload, dns and connection are usually 0: the answer was cached and the connection was reused.
  • load is later than domContentLoaded, often by far: it waits for images too.

Record your own numbers. Network, device and browser all change the results, so there is no single correct value.

Tracks your place during this browser session. Sign in to save it to your account.

Next stepPractice

Predict before you check.

Five questions. Commit to an answer, then read why each option is right or wrong.

Go to practice