#LearningPatterns52 | Based on “Learning Patterns” (v1.1) by Lydia Hallie & Addy Osmani
This article continues the Optimize Loading Sequence pattern. Part 1 covered why sequencing is hard and which metrics matter. Here in Part 2 we move from diagnosis ➜ prescription.
Introduction
The book frames loading as a queue‐management problem: which byte hits the wire first, and why?
The browser already has heuristics, but you — not the network stack — know what the user must see & use first.
Your job: override defaults with hints that pull critical assets forward and push distractions back.
1 · Critical CSS
Learning Patterns defines critical CSS as the minimal style‑set required to paint above‑the‑fold content.
The recommended flow:
-
Inline ≤ 15 KB of critical rules in the
<head> - Mark the remainder with
rel="preload"&as="style" - Defer non‑render‑blocking styles via
media="print"→onloadswap
The book’s Lighthouse trace shows a 31 % LCP improvement simply by isolating 5.8 KB of hero styles.
2 · Fonts
Fonts block text render. The pattern suggests:
-
preloadthe most‑used weight (woff2) - Combine
font-display: swapplus a 3 s FOIT timeout - Scope icon fonts to subsets or shift them to SVG sprites
Example: a P75 mobile session saw CLS drop from 0.23 ➜ 0.04 after the fallback/swap approach.
3 · Images
Above‑the‑Fold
Learning Patterns advises:
| Step | Tactic |
|---|---|
| 1 | Use a low‑quality placeholder (lqip, SVG blur) |
| 2 | Send the hero via fetchpriority="high" or HTTP/2 push |
| 3 | Serve modern formats (AVIF, WebP) |
Below‑the‑Fold
Mark with loading="lazy" and, if bandwidth is tight, wrap in an IntersectionObserver to delay even the request creation.
4 · Scripts
First‑Party JS
- Split: isolate hydration logic required for the initial route
- Defer modules that act post‑interactive
- Move expensive polyfills behind feature detection
Third‑Party JS
The authors label them “performance dark matter.” Recommendations:
- Convert blocking
<script>tags toasyncor delayed import - Stub APIs until after TTI (e.g., push calls into a queue)
- Load via a single proxy host to reuse TCP/QUIC connections
5 · How Chrome Prioritises Resources (Book Table)
| Priority Bucket | Examples | TLS Handshake? | Queue Age Limit |
|---|---|---|---|
| Highest | In‑document CSS, critical preload
|
Yes | Immediate |
| High | Images with fetchpriority="high"; JS in <head>
|
Yes | 5 round‑trips |
| Medium | Deferred/async scripts; fonts | If needed | 10 round‑trips |
| Low | Lazy images, rel="prefetch"
|
If idle | Infinite |
| Lowest | rel="prerender" |
Only when idle | Infinite |
(Table reproduced from *Learning Patterns, ch. “Optimize Loading Sequence”)*
6 · Case Study — Next.js SSR (Before Optimisation)
“Even modern SSR frameworks can ship bytes in the wrong order.” — Learning Patterns
Default Sequence
1. _app.js (159 KB) ← blocking
2. vendors.js (321 KB) ← blocking
3. route page.js (71 KB)
4. main.css (34 KB)
5. hero.jpg (1.2 MB)
6. webfont.woff2 (96 KB)
Impact:
- LCP (mobile): 4.8 s
- TBT: 620 ms (main thread busy parsing JS)
- CLS: 0.19 (font & image late)
The book’s flame chart shows the browser idle for 200 ms waiting on main.css that arrived after two big JS bundles.
7 · Proposed Sequence (No 3rd‑Party)
1. critical.css (inline) ← paints header
2. hero.jpg?width=560&format=avif ← fetched with fetchpriority=high
3. font.woff2 (preload) ← text remains stable
4. route page.js (hydration + suspense)
5. vendors.js (chunked + deferred)
6. rest.css (preloaded; onload rel=stylesheet)
Reasons
- Inline critical CSS unblocks first paint.
- Hero image early fetch secures LCP.
- Font preload prevents FOUT/CLS.
- Code‑split hydration chunk cuts TBT by trimming unused routes.
8 · Proposed Sequence (With 3rd‑Party)
1‒4. Same as above
5. stub-analytics.js (1 KB inline) ← captures events in queue
6. thirdparty.js (async, after load) ← executes post‑TTI
7. chat-widget.css (preload, media=print) ← swapped on scroll
Reasons
- A 1 KB stub guarantees data isn’t lost but doesn’t block painting.
- Full analytics, A/B test, or chat scripts run after TTI, avoiding TBT spikes.
- Widget styles load off‑screen, so they’re quarantined from first paint.
Conclusion
Learning Patterns’ big takeaway: ordering beats bandwidth.
By nudging the browser’s queue, you can often shave >30 % off LCP without new servers or CDNs.
Happy shipping! 🚀
All figures & workflow steps are reproduced or summarised from “Learning Patterns” (v1.1).
Top comments (0)