What is progressive rendering?
TL;DR
Progressive rendering makes a page useful incrementally instead of waiting for every resource and component to finish. Deliver meaningful HTML early, prioritize the resources needed for the initial view, stream later content when appropriate, and defer or lazy-load noncritical work. Do not lazy-load the likely Largest Contentful Paint image, and measure real paint, layout-shift, and interaction metrics rather than equating “more lazy loading” with better performance.
What is progressive rendering?
Progressive rendering is a delivery strategy, not one browser API. The server and browser reveal useful content in stages while slower data, images, and JavaScript continue loading.
Send useful HTML early
Server-rendered or static HTML can display headings, navigation, and primary content before client JavaScript initializes. A server can also stream HTML as data becomes available, but the chunks should preserve document order, error handling, and a usable experience when JavaScript is slow or unavailable.
Placeholders should reserve the final component's space so later content does not cause unexpected layout shifts. A skeleton is helpful only when it communicates progress and does not replace content that could have been rendered immediately.
Prioritize critical resources
- Discover required CSS and fonts early, but keep the critical path small.
- Use
deferor modules for application scripts that do not need to block parsing. - Preload only resources known to be required soon; unnecessary preloads compete for bandwidth.
- Serve responsive images with intrinsic dimensions to avoid layout shifts.
Lazy-load noncritical content
Native image lazy loading is appropriate for images below the initial viewport:
<imgsrc="/gallery/photo-800.jpg"alt="A mountain reflected in a lake"width="800"height="533"loading="lazy" />
Do not set loading="lazy" on an image likely to be the page's Largest Contentful Paint element. For custom deferred UI, IntersectionObserver is more robust than handling every scroll event manually. Dynamic imports can delay noncritical JavaScript, but excessive splitting adds requests and loading states.
Framework techniques such as progressive or selective hydration are implementation options, not requirements of progressive rendering. Their benefit depends on how much JavaScript the page needs and when users can interact with it.
Measure the result
Use throttled Network and Performance recordings plus field data where available. First Contentful Paint and Largest Contentful Paint reveal display progress, Cumulative Layout Shift catches unstable staging, and Interaction to Next Paint helps show whether deferred JavaScript still blocks users later.
Further reading
- Web performance | MDN
- Browser-level image lazy loading | web.dev
- Optimize Largest Contentful Paint | web.dev
- Streams API | MDN