DEV Community

Cover image for Optimize Loading Sequence (Part 2)
Md Enayetur Rahman
Md Enayetur Rahman

Posted on

Optimize Loading Sequence (Part 2)

#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:

  1. Inline ≤ 15 KB of critical rules in the <head>
  2. Mark the remainder with rel="preload" & as="style"
  3. Defer non‑render‑blocking styles via media="print"onload swap

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:

  • preload the most‑used weight (woff2)
  • Combine font-display: swap plus 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:

  1. Convert blocking <script> tags to async or delayed import
  2. Stub APIs until after TTI (e.g., push calls into a queue)
  3. 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)
Enter fullscreen mode Exit fullscreen mode

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)
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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)