How Declarative Partial Updates Work in HTML


HTML has always supported streaming. The server doesn’t need to build an entire page in memory before sending it to the browser. It can send the initial HTML first, then send more chunks as each chunk is ready. The browser parses those chunks and displays the page in order. This is one reason why HTML seems fast.

But traditional HTML streaming has a strict rule. The HTML comes in the order of the document. If the browser gets the header first, then the sidebar, and finally the main content, it parses those chunks in that order. If a slow database query blocks a chunk of the page early on, the next chunk often has to wait until it’s ready on the server.

JavaScript frameworks have been solving this problem for years. Server-rendering frameworks handle shell, suspense boundaries, loading state, and late content streaming. Some frameworks use inline script to patch the existing DOM. Libraries like HTMX allow developers to update parts of a page with server-generated HTML.

But these solutions require JavaScript somewhere. Declarative Partial Updates raise a different question. What if HTML had its own way of saying,

When this content comes in, put it there?

That’s the idea behind Chrome’s declarative partial updates proposal.

In this article, you’ll learn what problems declarative partial updates aim to solve, how the proposed placeholder syntax works, how out-of-order HTML streaming differs from normal streaming, how the related JavaScript HTML insertion APIs fit in, and why it should be considered an experimental feature of the browser rather than production-ready HTML.

Table of Contents

What Problem Declarative Partial Updates Try to Solve

Consider a product page. The server already knows the page title, navigation, footer, and product details. But the recommendations section requires a slow database query. With traditional server-rendered HTML, you have two common options:

  • First, the server waits until everything is ready, then sends a full HTML response. This keeps the code simple, but the user waits a long time before seeing anything useful.

  • Second, the server streams the HTML in stages. It sends the top of the page first, then sends the rest as it’s ready. This seems to improve performance, because the browser starts rendering before the full response is finished.

But streaming alone doesn’t completely solve this problem. The browser still parses the HTML sequentially. If there’s a slow recommendation block at the beginning of the document, the content after that block will wait behind it, unless you restructure the document, add JavaScript, or use a framework abstraction.

WICG Patching Explainer describes two limitations of traditional HTML streaming:

  1. HTML content is streamed in DOM order.

  2. After the initial document parsing step, streaming is no longer as active as before.

Declarative partial update attempts to relax the first limitation. It allows the server to first send a placeholder and then send the actual content in the response. The browser applies that next content over the previous placeholder. This patch doesn’t require any custom client-side DOM patching code.

Diagram showing traditional HTML streaming.

In the above diagram, the server sends HTML chunks in sequence. The browser can render early chunks before the response ends, but the rendered order still follows the response order.

How Traditional HTML Streaming Works

Before studying the proposal, you need to understand its basic structure. A server sends an HTTP response body. That body contains HTML. The browser reads the response as soon as it arrives. It doesn’t need to wait for the entire response body to parse the first tags.

Here’s a tiny Node.js example:

import http from "node:http";

const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));

const server = http.createServer(async (req, res) => {
    res.writeHead(200, {
        "Content-Type": "text/html; charset=utf-8",
    });

    res.write(`
    
    
      
        Normal HTML Streaming
      
      
        
        

This part arrives first.

`); await sleep(2000); res.write(`

This part arrives after two seconds.

`); await sleep(2000); res.end(`

This part arrives after four seconds.

`); }); server.listen(3000, () => { console.log("Server running at http://localhost:3000"); });

This example creates a small HTTP server using Node’s built-in http module. When you visit the page, the server sends a response in three separate HTML chunks.

The first res.write() immediately sends the document shell, title, and first paragraph. Then sleep(2000) pauses the server for two seconds before the next res.write() sends another paragraph. After another pause, res.end() sends the last paragraph and closes the HTML document.

The browser starts rendering the first chunk before the entire response is complete, then adds subsequent paragraphs as more HTML arrives.

This demonstrates that simple HTML streaming works, but the content is displayed in the same order that the server sends it.

Now open this page in a browser.

http://localhost:3000

You’ll see the first part of the page before the entire response is complete. As the server sends more chunks, the browser continues to load.

This behavior is old and functional. But notice its structure. The server writes the first paragraph, then the second paragraph, and then the third paragraph. The browser receives them in the same order. It also places them in the DOM in the same order.

Traditional streaming lets you send previous content first. But it doesn’t give you a native way to say that this next chunk will be inside a previous placeholder. Declarative partial updates target that missing part.

Why Frameworks Already Work Around This Problem

Modern frameworks already create experiences where parts of a page are rendered as they’re ready. React server components and suspense-based server rendering are common examples. A framework can first send a shell, show a fallback, and then stream the full content later.

But the browser doesn’t understand a React boundary as native HTML. The framework has to encode its own protocol. As the WICG patching explainer notes, React uses inline



Source link

Leave a Comment

Your email address will not be published. Required fields are marked *

Scroll to Top