Performance
Course 3 · Ch 9
Performance
The critical rendering path, lazy loading, and resource hints — the HTML-level techniques that genuinely affect load speed
Most performance advice focuses on JavaScript and CSS optimisation — this chapter covers what HTML markup itself can do, often with a single attribute, to measurably improve how quickly a page becomes usable.
The Critical Rendering Path — What the Browser Actually Does First
A <script> tag (without async/defer) encountered mid-parse BLOCKS this entire sequence until it finishes downloading and executing
The browser parses HTML top to bottom, building the DOM as it goes — but a plain <script> tag stops everything until that script downloads and runs, which is exactly why blocking scripts in <head> were historically such a common performance problem.
// Blocks parsing until downloaded AND executed — avoid in <head> for non-critical scripts
<script src="analytics.js"></script>
// Downloads in parallel with parsing, executes in document order once ready
<script src="app.js" defer></script>
// Downloads in parallel, executes immediately whenever it finishes — order not guaranteed
<script src="widget.js" async></script>
defer vs async — they solve genuinely different problems
defer guarantees scripts run in document order, after parsing completes — the right default for most app code that depends on the DOM or on running in a specific sequence. async makes no ordering guarantee at all — appropriate for independent, self-contained scripts (a standalone analytics snippet) that don't depend on anything else or need to run at a specific point.
Lazy Loading — Deferring Off-Screen Content
<img src="photo.jpg" loading="lazy" alt="...">
<iframe src="..." loading="lazy" title="..."></iframe>
A single attribute defers loading until the element is about to scroll into view — already mentioned for iframes in Intermediate Chapter 4, and equally valuable on images, especially for a long page with many images further down that most visitors never reach.
Never lazy-load the image visible immediately on page load
Applying loading="lazy" to a hero image or anything visible without scrolling actively delays it unnecessarily — the browser still has to detect it's "in view" before starting the load, adding latency to exactly the content a visitor sees first. Reserve lazy loading specifically for genuinely below-the-fold content.
Resource Hints — preload, prefetch, preconnect
| Hint | Tells the browser to | Use for |
|---|---|---|
| preload | Fetch this resource NOW, with high priority — it's needed very soon | A critical font or hero image the page needs immediately |
| prefetch | Fetch this resource at low priority, for likely future use | A resource needed on the NEXT page a user will probably visit |
| preconnect | Establish the connection (DNS, TCP, TLS) to a domain early, without fetching anything yet | A third-party domain (CDN, API) you know you'll request from soon |
<link rel="preload" href="/fonts/main.woff2" as="font" type="font/woff2" crossorigin>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="prefetch" href="/next-page-assets.js">
preload is specifically for THIS page; prefetch is a bet on the NEXT one
Using preload for something not genuinely needed immediately wastes bandwidth competing with resources that actually are urgent — the browser takes the priority hint seriously. Reserve preload for what this exact page needs right away; use prefetch when there's a real, well-justified expectation of where the user is headed next (the obvious "next chapter" link in a course, for instance).
Why HTML-Level Performance Still Matters Alongside JS/CSS Optimisation
- These changes require no build tooling. A single attribute or link tag, no bundler configuration, no framework-specific optimisation plugin.
- They affect the very earliest part of the load, before any JavaScript has even had a chance to run — exactly the window where a slow, render-blocking resource costs the most in perceived performance.
- They're measurable directly via the Network tab's waterfall view and Lighthouse's performance audit, both of which flag missing lazy-loading and render-blocking resources explicitly.
Chapter 9 Quick Reference
- Critical rendering path: parse HTML → build DOM → build CSSOM → render/paint; a blocking script stops this entire sequence
- defer — runs in document order after parsing; async — runs immediately on completion, no ordering guarantee
- loading="lazy" on images/iframes — defer off-screen content; never apply to anything visible without scrolling
- preload — high priority, needed now; prefetch — low priority, needed on a likely next page; preconnect — early connection setup only
- These are HTML-level, zero-build-tooling wins — measurable directly via Network waterfall and Lighthouse
- Next chapter: HTML5 APIs grab-bag — Geolocation, Notifications, Clipboard API