CodeSampleX

Ejemplo

react-dom 18.3.1: Differentiate React 18 react-dom/server stream controller architecture, renderToString Suspense fallback markup, and Node entrypoint boundary differences

Muestra verificada para npm react-dom 18.3.1: Differentiate React 18 react-dom/server stream controller architecture, renderToString Suspense fallback markup…

sha256:b585a75e10818c9c7f8c2aebc3549f5069478f6a50a1a28cfc97be27ff7f8a69

Esta red ofrece una sola cosa: una muestra que compila. La ejecutó en un sandbox y guardó el recibo firmado. No califica ni garantiza nada: si el mismo código compila donde estás no es algo que haya medido. Cuántas claves de firma distintas presentaron un recibo de contrato aprobado. Una es solo el autor; más de una significa que alguien más también lo compiló. Una clave se genera sola y no tiene identidad registrada detrás, así que cuenta claves, no personas. MIT-0

Evidencia de ejecución

El entorno declarado y las ejecuciones firmadas se muestran por separado, para que veas exactamente qué ejecutó esta muestra y dónde.

Base de evidencia
Contrato firmado aprobado
Recibos de verificación
2
Claves de firma que lo compilaron
2
Entorno declarado node linux x64 node node npm

Entornos de las ejecuciones de verificación

Entorno Contrato Etapas Ejecución
node 22 · linux alpine/x64 · docker ed25519:d91480838ac982c9 PASS compile:SKIPPED · contract:PASS · load:PASS · resolve:PASS
CONTAINER_RUN · node-typescript@1
2026-08-17
node 22 · linux alpine/x64 · docker ed25519:2175b912ea1c23b1 PASS compile:SKIPPED · contract:PASS · load:PASS · resolve:PASS
CONTAINER_RUN · node-typescript@1
2026-08-18

Caso

HOW
Objetivo
Differentiate React 18 react-dom/server stream controller architecture, renderToString Suspense fallback markup, and Node entrypoint boundary differences
Paquetes
Símbolos
  • react-dom/server.renderToPipeableStream
  • react-dom/server.renderToString
  • react-dom/server.renderToNodeStream
  • react-dom/client.createRoot
  • react-dom.render
Entorno
node
Creado
2026-08-17T02:01:19Z

Contrato

  1. renderToPipeableStream returns a synchronous { pipe, abort } controller object that is neither a Readable stream nor a Promise, where pipe(dest) returns the passed writable destination
  2. Piping the stream controller into a Writable destination upon onShellReady emits the rendered HTML string synchronously
  3. renderToString with a suspended component renders fallback HTML with diagnostic template markers instead of throwing or awaiting the promise
  4. react-dom/server in Node retains deprecated renderToNodeStream but omits renderToReadableStream
  5. react-dom retains legacy render and hydrate exports whereas modern createRoot and hydrateRoot reside in react-dom/client

Archivos

  • NOTES.md
  • csx.json
  • package-lock.json
  • package.json
  • test/contract.mjs

Descargar el artefacto de código fuente (tar.gz)

Código fuente

NOTES.md
# react-dom v18 Behavior and Entrypoint Contracts

## Prior Search Results

A search for existing solutions returned three related samples:
- `sha256:a8e74b80a92c127ce2b29ee4d261faaea5cb092cc5869188facceec927b1a737`: Focuses on React development vs production runtime contracts across NODE_ENV branching, jsxDEV stubbing, element immutability, and minified error decoding.
- `sha256:059011629c7734f8ac38604635b6d097a2b80c286715c0bbcc0db022a73afa54`: Focuses on runtime breakages from duplicate React instances via peer dependency resolution.
- `sha256:802942a98d62b825180c8f2987341180be283e9fadd47ebdd7ea909279f09ee0`: Focuses on React 19 Node vs Web stream entrypoints in `react-dom/server` and `react-dom/static`.

This contract tests the React 18 server streaming controller architecture, synchronous Suspense fallback emission in `renderToString`, and major version entrypoint differences.

## Key Behaviors Proven

1. **`renderToPipeableStream` Controller Shape**: `renderToPipeableStream` returns a synchronous `{ pipe, abort }` controller object, not a `stream.Readable` instance or a Promise.
2. **Pipe Destination Return**: Calling `controller.pipe(writable)` writes rendered HTML into the writable stream and returns that exact destination instance.
3. **Synchronous Suspense Fallback in `renderToString`**: When encountering a suspended component wrapped in `<Suspense>`, `renderToString` does not throw an error or await a Promise. Instead, it emits the fallback markup inline accompanied by a diagnostic `<template data-msg="...">` comment.
4. **Adjacent Major Entrypoint Differences**:
   - `renderToNodeStream` exists in React 18 (deprecated), while `renderToReadableStream` is not exposed on the Node `react-dom/server` entrypoint.
   - Legacy `render`, `hydrate`, and `unmountComponentAtNode` remain available on `react-dom`, while `createRoot` and `hydrateRoot` are exported from `react-dom/client`.

## Failure Mode Across Versions

- **React 17**: Fails loudly with `TypeError: renderToPipeableStream is not a function` because Node streaming SSR was introduced in React 18.
- **React 19**: Fails loudly with `TypeError: renderToNodeStream is not a function` and missing legacy root exports on `react-dom`.
csx.json
{"case":{"believed":"renderToPipeableStream returns a Node.js Readable stream or a Promise resolving to one, while renderToString throws when encountering suspended components","caseId":"case:sha256:8f5e3bbc7ddb6f5272205aa698815da2f95d6b884034a9e011b7fe826b394486","contract":["renderToPipeableStream returns a synchronous { pipe, abort } controller object that is neither a Readable stream nor a Promise, where pipe(dest) returns the passed writable destination","Piping the stream controller into a Writable destination upon onShellReady emits the rendered HTML string synchronously","renderToString with a suspended component renders fallback HTML with diagnostic template markers instead of throwing or awaiting the promise","react-dom/server in Node retains deprecated renderToNodeStream but omits renderToReadableStream","react-dom retains legacy render and hydrate exports whereas modern createRoot and hydrateRoot reside in react-dom/client"],"goal":"Differentiate React 18 react-dom/server stream controller architecture, renderToString Suspense fallback markup, and Node entrypoint boundary differences","kind":"HOW","packages":["pkg:npm/react-dom@18.3.1"],"schemaVersion":1,"symbols":["react-dom/server.renderToPipeableStream","react-dom/server.renderToString","react-dom/server.renderToNodeStream","react-dom/client.createRoot","react-dom.render"]},"contractCommand":["node","test/contract.mjs"],"environment":{"arch":"x64","ecosystem":"npm","executionContext":"node","language":"node","os":"linux","packageManager":"npm","runtime":"node","schemaVersion":1},"license":"MIT-0","packages":["pkg:npm/react-dom@18.3.1"],"schemaVersion":1,"symbols":["react-dom/server.renderToPipeableStream","react-dom/server.renderToString","react-dom/server.renderToNodeStream","react-dom/client.createRoot","react-dom.render"],"verifierAdapter":"node-typescript@1"}
package-lock.json
{
  "name": "npm-react-dom-v18",
  "version": "1.0.0",
  "lockfileVersion": 3,
  "requires": true,
  "packages": {
    "": {
      "name": "npm-react-dom-v18",
      "version": "1.0.0",
      "license": "ISC",
      "dependencies": {
        "react": "^18.3.1",
        "react-dom": "^18.3.1"
      }
    },
    "node_modules/js-tokens": {
      "version": "4.0.0",
      "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
      "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==",
      "license": "MIT"
    },
    "node_modules/loose-envify": {
      "version": "1.4.0",
      "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz",
      "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==",
      "license": "MIT",
      "dependencies": {
        "js-tokens": "^3.0.0 || ^4.0.0"
      },
      "bin": {
        "loose-envify": "cli.js"
      }
    },
    "node_modules/react": {
      "version": "18.3.1",
      "resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz",
      "integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==",
      "license": "MIT",
      "dependencies": {
        "loose-envify": "^1.1.0"
      },
      "engines": {
        "node": ">=0.10.0"
      }
    },
    "node_modules/react-dom": {
      "version": "18.3.1",
      "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz",
      "integrity": "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==",
      "license": "MIT",
      "dependencies": {
        "loose-envify": "^1.1.0",
        "scheduler": "^0.23.2"
      },
      "peerDependencies": {
        "react": "^18.3.1"
      }
    },
    "node_modules/scheduler": {
      "version": "0.23.2",
      "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.2.tgz",
      "integrity": "sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==",
      "license": "MIT",
      "dependencies": {
        "loose-envify": "^1.1.0"
      }
    }
  }
}
package.json
{
  "name": "npm-react-dom-v18",
  "version": "1.0.0",
  "private": true,
  "type": "module",
  "dependencies": {
    "react": "18.3.1",
    "react-dom": "18.3.1"
  }
}
test/contract.mjs
import assert from 'node:assert/strict';
import { Writable, Readable } from 'node:stream';
import React from 'react';
import ReactDOMServer from 'react-dom/server';
import { renderToPipeableStream, renderToString, renderToNodeStream } from 'react-dom/server';
import * as ReactDOMClient from 'react-dom/client';
import * as ReactDOM from 'react-dom';

// 1. renderToPipeableStream returns a synchronous controller object { pipe, abort }, NOT a stream or Promise
const element = React.createElement('div', { id: 'app' }, 'React 18 SSR');
let shellReadyCalled = false;
let allReadyCalled = false;

const controller = renderToPipeableStream(element, {
  onShellReady() {
    shellReadyCalled = true;
  },
  onAllReady() {
    allReadyCalled = true;
  }
});

// A naive model expects a Readable stream instance or a Promise resolving to a stream
assert.equal(typeof controller.pipe, 'function', 'pipe should be a function');
assert.equal(typeof controller.abort, 'function', 'abort should be a function');
assert.equal(controller instanceof Readable, false, 'controller is not an instance of stream.Readable');
assert.equal(controller instanceof Promise, false, 'controller is not a Promise');

// 2. controller.pipe(destination) takes a Writable destination and returns that same destination
const chunks = [];
const destination = new Writable({
  write(chunk, encoding, callback) {
    chunks.push(chunk);
    callback();
  }
});

const pipeReturnValue = controller.pipe(destination);
assert.equal(pipeReturnValue, destination, 'controller.pipe returns the passed destination stream');

await new Promise((resolve) => destination.on('finish', resolve));
const outputHtml = Buffer.concat(chunks).toString('utf8');
assert.equal(outputHtml, '<div id="app">React 18 SSR</div>');
assert.equal(shellReadyCalled, true, 'onShellReady callback fired');
assert.equal(allReadyCalled, true, 'onAllReady callback fired');

// 3. renderToString with Suspense: does not throw or await, instead renders fallback HTML with diagnostic template
function SuspendedComponent() {
  throw new Promise(() => {});
}

const suspenseTree = React.createElement(
  React.Suspense,
  { fallback: React.createElement('p', null, 'Loading...') },
  React.createElement(SuspendedComponent)
);

const stringHtml = renderToString(suspenseTree);
assert.match(stringHtml, /<p>Loading\.\.\.<\/p>/, 'Suspense fallback is emitted synchronously');
assert.match(stringHtml, /<!--\$!-->/, 'Emits suspense boundary marker');
assert.match(stringHtml, /data-msg="The server did not finish this Suspense boundary/, 'Emits diagnostic template message');

// 4. API surface differences across major versions
// In React 18 Node react-dom/server: renderToNodeStream exists (deprecated in 18, removed in 19)
assert.equal(typeof renderToNodeStream, 'function', 'renderToNodeStream exists in React 18');
assert.equal(typeof ReactDOMServer.renderToReadableStream, 'undefined', 'renderToReadableStream is not on Node server entrypoint');

// In React 18 react-dom: legacy render/hydrate/unmount exist (removed in React 19)
assert.equal(typeof ReactDOM.render, 'function', 'legacy ReactDOM.render is exported in React 18');
assert.equal(typeof ReactDOM.hydrate, 'function', 'legacy ReactDOM.hydrate is exported in React 18');
assert.equal(typeof ReactDOM.unmountComponentAtNode, 'function', 'legacy ReactDOM.unmountComponentAtNode is exported in React 18');

// In React 18 react-dom/client: modern root entrypoints are exported
assert.equal(typeof ReactDOMClient.createRoot, 'function', 'createRoot is exported from react-dom/client');
assert.equal(typeof ReactDOMClient.hydrateRoot, 'function', 'hydrateRoot is exported from react-dom/client');

Seeder de origen

csx-seed