Put the LCP element on the critical path

React chapter 147 · Web Perf · ch.9 · lazy boundaries, what goes in the first chunk, skeletons · source: Nadia Makarevich, Web Performance Fundamentals, Chapter 9 (Advanced lazy loading: loading critical elements first, preloading lazy chunks)

The problem

The whole dashboard page — layout, title, sidebar, widgets — sits inside one lazy() chunk behind one Suspense boundary. Code splitting made the first JS smaller, but the page title (the LCP element) now waits for the slowest chunk. The user stares at a blank area.

The pattern that fixes it

Decide what must paint first and keep it out of the lazy boundary: the layout and the LCP element ship in the main chunk. Lazy-load what is below or beside it, each with a skeleton of its real size. Then preload the next likely chunks after the page is up.

In plain words

Splitting code is choosing an order. Everything inside a <Suspense> boundary waits for its chunk; everything outside it shows as soon as the main bundle runs. Put the most important thing outside.

A restaurant brings bread and water the moment you sit down, and the main course when it is ready. It does not make you sit at an empty table until every dish is cooked.

Terms

critical path
The code and resources that must load before the first meaningful paint.
lazy boundary
lazy(() => import(…)) + <Suspense>. The fallback shows until that chunk loads.
LCP element
The largest text or image in the viewport. DevTools → Performance → LCP → “related node” tells you which.

Going deeper

Find the LCP element first

Record the page in the Performance panel, click the LCP marker and read the related node. Often it is a heading or hero image you did not expect. Trace it to the component that renders it, then trace which lazy boundary it lives under. In the book, moving AppLayout out of the lazy page dropped LCP ~300 ms; lazy-loading the sidebar saved another 65 ms.

Preload after the critical path

Splitting makes the next navigation wait for its chunk. Fix: after the page renders, import("./settings") the likely next routes (they download at low priority and do not block LCP), or preload from your Link on hover/focus (chapter 100). Frameworks do this per route automatically.

Skeletons and CLS

A fallback that is smaller than the content causes a layout shift when the chunk arrives (chapter 144). Give each skeleton the real dimensions. Prefer one boundary per independent region over one boundary for the page, so a slow widget does not hold back a fast one.

With SSR

With streaming SSR the same thinking applies on the server: content outside Suspense is in the first HTML flush, content inside streams later (chapter 109). Lazy components without SSR support render their fallback into the HTML — never wrap the LCP element that way.

Keep learning

More courses

  • Jobs, linked to lessons — Browse jobs where every requirement links to the chapter that teaches it. See how ready you are, how long the gap takes to close, and which listings look stale.
  • Match a job post to courses — Paste a job post. Each skill is matched to a track here and put in learning order, foundations first.
  • Database in depth — How a query becomes work. Indexes, isolation, locks, and the plans that explain why a page is slow — not an ORM tour.
  • System Design — Eight interview case studies, from a flash sale and Tatkal to a live final and a chat model, plus JWT in separate chapters.
  • Microservices — Microservice patterns one diagram at a time: how to split a monolith, how services talk, and how data stays consistent without distributed transactions.
  • Kafka — A beginner-to-senior path through event logs, reliable delivery, production operations, and disaster recovery.
  • Frontend system design — How a UI is sliced when it is a product, not a page: ownership of state, cache, routes, and what happens when the network lies.
  • CSS in depth — See the box, then the page. Visual chapters from the box model through Flexbox surprises, Grid, selectors, and units, then backgrounds, shapes, and visual effects, each with a playground.
  • Accessibility — HTML labs first, then a full pass of WAI-ARIA 1.3: naming, every state, widget and structure roles, live regions, ariaNotify, and relationships.
  • Docker — What an image is, why layers cache, and how containers find each other on a network.
  • Redis — Fifteen Redis patterns, one picture each: cache, session, lock, counter, rate limiter, queue, and when Redis is the wrong tool.