Understanding React 16 Server‑Side Rendering (SSR) and Its Rendering Strategies
This article explains how React 16 rewrote its server‑side rendering layer to support four rendering modes—including string and streaming approaches—by introducing the ReactPartialRenderer and ReactMarkupReadableStream classes, and details the process of converting virtual DOM trees into HTML strings.
React 16 rewrote its Server‑Side Rendering (SSR) implementation, offering four rendering APIs: two that return a complete string and two that return a stream, all built on the internal ReactPartialRenderer and ReactMarkupReadableStream classes.
The streaming variants use ReactMarkupReadableStream, which extends Readable and reads the rendered markup in chunks, allowing the browser to display content progressively instead of waiting for the whole HTML string.
//我们需要继续stream中的Readable
class ReactMarkupReadableStream extends Readable {
constructor(element, makeStaticMarkup) {
super({});
this.partialRenderer = new ReactPartialRenderer(element, makeStaticMarkup);
}
_read(size) {
try {
this.push(this.partialRenderer.read(size));
} catch (err) {
this.emit('error', err);
}
}
}Two helper functions expose the stream APIs:
export function renderToNodeStream(element) {
return new ReactMarkupReadableStream(element, false);
}
export function renderToStaticNodeStream(element) {
return new ReactMarkupReadableStream(element, true);
}For the string‑based APIs, the renderer creates a ReactPartialRenderer, reads the entire markup with Infinity as the size, and returns the resulting HTML.
export function renderToString(element) {
const renderer = new ReactPartialRenderer(element, false);
const markup = renderer.read(Infinity);
return markup;
}
export function renderToStaticMarkup(element) {
const renderer = new ReactPartialRenderer(element, true);
const markup = renderer.read(Infinity);
return markup;
}The core of the conversion lives in ReactDOMServerRenderer.renderDOM. It creates a Frame object that represents a native virtual DOM node, pushes it onto an internal stack, and returns the opening tag string. A Frame contains fields such as type, domNamespace, children, childIndex, context, and footer, which together describe how to serialize the node.
const frame: Frame = {
type: null | string,
domNamespace: parentNamespace,
children: nextChildren,
childIndex: 0,
context: context,
footer: ''
};The renderDOM function builds this frame, pushes it onto this.stack, and then generates the opening tag by concatenating the element type and its filtered attributes (excluding internal props like key, ref, event handlers, and boolean false values). The closing tag (footer) is added when the frame represents the last child of its parent.
renderDOM(element, context, parentNamespace) {
// ... omitted for brevity
const frame = {
domNamespace: getChildNamespace(parentNamespace, element.type),
type: tag,
children,
childIndex: 0,
context,
footer
};
this.stack.push(frame);
this.previousWasTextNode = false;
return out;
}Component virtual DOM is handled similarly: the render method creates a frame for the component, resolves it to a concrete element tree, and then serializes it using the same logic.
Driving the whole process starts with new ReactPartialRenderer(element, isStatic), which creates the first frame. The read(size) method repeatedly pops frames from the stack, renders them, and appends their opening tags (and footers when needed) to the output until the requested size is reached or the tree is exhausted.
In summary, React 16’s SSR provides a lightweight, high‑performance rendering pipeline that avoids reusing the reconciler code, but it does not handle edge‑case errors inside component lifecycles, nor does it address SPA‑specific optimizations such as code‑splitting, CSS injection, or shared data stores—tasks that are typically delegated to frameworks like Next.js.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Qunar Tech Salon
Qunar Tech Salon is a learning and exchange platform for Qunar engineers and industry peers. We share cutting-edge technology trends and topics, providing a free platform for mid-to-senior technical professionals to exchange and learn.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
