{"id":20838785,"url":"https://github.com/royalicing/rendertopipeablestreamplayground","last_synced_at":"2026-06-17T20:35:36.879Z","repository":{"id":72483439,"uuid":"488448891","full_name":"RoyalIcing/renderToPipeableStreamPlayground","owner":"RoyalIcing","description":null,"archived":false,"fork":false,"pushed_at":"2022-05-04T06:01:58.000Z","size":18,"stargazers_count":2,"open_issues_count":0,"forks_count":0,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-01-18T23:43:11.547Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/RoyalIcing.png","metadata":{"files":{"readme":"readme.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null}},"created_at":"2022-05-04T04:15:20.000Z","updated_at":"2023-03-05T06:33:51.000Z","dependencies_parsed_at":"2023-02-23T07:15:13.250Z","dependency_job_id":null,"html_url":"https://github.com/RoyalIcing/renderToPipeableStreamPlayground","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/RoyalIcing%2FrenderToPipeableStreamPlayground","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/RoyalIcing%2FrenderToPipeableStreamPlayground/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/RoyalIcing%2FrenderToPipeableStreamPlayground/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/RoyalIcing%2FrenderToPipeableStreamPlayground/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/RoyalIcing","download_url":"https://codeload.github.com/RoyalIcing/renderToPipeableStreamPlayground/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":243196662,"owners_count":20251861,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-18T01:11:33.164Z","updated_at":"2025-10-08T12:09:02.560Z","avatar_url":"https://github.com/RoyalIcing.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Understanding React’s `renderToPipeableStream()`\n\nRead the [`renderToPipeableStream()` documentation](https://reactjs.org/docs/react-dom-server.html#rendertopipeablestream)\n\nI made this so I could understand how it works enough to improve the documentation [(see PR)](https://github.com/reactjs/reactjs.org/pull/4623)\n\n---\n\n```js\nfunction App({ resource, suspends }) {\n  return (\n    \u003chtml\u003e\n      \u003chead /\u003e\n      \u003cbody\u003e\n        {suspends ? (\n          \u003cSuspense fallback={\u003cp\u003eLoading\u003c/p\u003e}\u003e\n            \u003cLoader /\u003e\n          \u003c/Suspense\u003e\n        ) : (\n          \u003cp\u003eStatic content\u003c/p\u003e\n        )}\n      \u003c/body\u003e\n    \u003c/html\u003e\n  );\n}\n\nfunction Loader({ resource }) {\n  const value = useResource(resource);\n  return \u003cp\u003e{value}\u003c/p\u003e;\n}\n\nconst resource = createResource();\nReactDOMServer.renderToPipeableStream(\n  \u003cApp resource={resource} suspends={suspends} /\u003e\n);\n```\n\n---\n\nWhat happens when? —\n\n- When we have just static content (no Suspense)\n  - ✅ Client-side JavaScript\n    1. `onShellReady()` and start piping\n    1. `onAllReady()`\n    1. stream closed with no error\n    1. writes static html:\n    ```html\n    \u003c!DOCTYPE html\u003e\n    \u003chtml\u003e\n      \u003chead\u003e\u003c/head\u003e\n      \u003cbody\u003e\n        \u003cp\u003eStatic content\u003c/p\u003e\n      \u003c/body\u003e\n    \u003c/html\u003e\n    ```\n  - ❌ No client-side JavaScript\n    1. `onShellReady()`\n    1. `onAllReady()` and start piping\n    1. stream closed with no error\n    1. writes static html:\n    ```html\n    \u003c!DOCTYPE html\u003e\n    \u003chtml\u003e\n      \u003chead\u003e\u003c/head\u003e\n      \u003cbody\u003e\n        \u003cp\u003eStatic content\u003c/p\u003e\n      \u003c/body\u003e\n    \u003c/html\u003e\n    ```\n- When `\u003cApp\u003e` throws an error\n  - ✅ Client-side JavaScript\n    1. `onError(error)`\n    1. `onShellError(error)`\n    1. stream closed with no error\n    1. no bytes written\n  - ❌ No client-side JavaScript\n    1. `onError(error)`\n    1. `onShellError(error)`\n    1. `onAllReady()` and start piping\n    1. stream closed with ⚠️ error\n    1. no bytes written\n- When content suspends on a resource that succeeds\n  - ✅ Client-side JavaScript\n    1. `onShellReady()` and start piping\n    1. `onAllReady()`\n    1. stream closed with no error\n    1. writes html with `\u003cscript\u003e`\n    ```html\n    \u003c!DOCTYPE html\u003e\n    \u003chtml\u003e\n      \u003chead\u003e\u003c/head\u003e\n      \u003cbody\u003e\n        \u003c!--$?--\u003e\u003ctemplate id=\"B:0\"\u003e\u003c/template\u003e\n        \u003cp\u003eLoading\u003c/p\u003e\n        \u003c!--/$--\u003e\n      \u003c/body\u003e\n    \u003c/html\u003e\n    \u003cdiv hidden id=\"S:0\"\u003e\u003cp\u003eResource loaded\u003c/p\u003e\u003c/div\u003e\n    \u003cscript\u003e\n      function $RC(a, b) {\n        a = document.getElementById(a);\n        b = document.getElementById(b);\n        b.parentNode.removeChild(b);\n        if (a) {\n          a = a.previousSibling;\n          var f = a.parentNode,\n            c = a.nextSibling,\n            e = 0;\n          do {\n            if (c \u0026\u0026 8 === c.nodeType) {\n              var d = c.data;\n              if (\"/$\" === d)\n                if (0 === e) break;\n                else e--;\n              else (\"$\" !== d \u0026\u0026 \"$?\" !== d \u0026\u0026 \"$!\" !== d) || e++;\n            }\n            d = c.nextSibling;\n            f.removeChild(c);\n            c = d;\n          } while (c);\n          for (; b.firstChild; ) f.insertBefore(b.firstChild, c);\n          a.data = \"$\";\n          a._reactRetry \u0026\u0026 a._reactRetry();\n        }\n      }\n      $RC(\"B:0\", \"S:0\");\n    \u003c/script\u003e\n    ```\n  - ❌ No client-side JavaScript\n    1. `onShellReady()`\n    1. `onAllReady()` and start piping\n    1. stream closed with no error\n    1. writes static html:\n    ```html\n    \u003c!DOCTYPE html\u003e\n    \u003chtml\u003e\n      \u003chead\u003e\u003c/head\u003e\n      \u003cbody\u003e\n        \u003c!--$--\u003e\n        \u003cp\u003eResource loaded\u003c/p\u003e\n        \u003c!--/$--\u003e\n      \u003c/body\u003e\n    \u003c/html\u003e\n    ```\n- When content suspends and `\u003cLoader\u003e` throws error\n  - ✅ Client-side JavaScript\n    1. `onError(error)`\n    1. `onShellReady()` and start piping\n    1. `onAllReady()`\n    1. stream closed with no error\n    1. writes static html:\n    ```html\n    \u003c!DOCTYPE html\u003e\n    \u003chtml\u003e\n      \u003chead\u003e\u003c/head\u003e\n      \u003cbody\u003e\n        \u003c!--$!--\u003e\n        \u003cp\u003eLoading\u003c/p\u003e\n        \u003c!--/$--\u003e\n      \u003c/body\u003e\n    \u003c/html\u003e\n    ```\n  - ❌ No client-side JavaScript\n    1. `onError(error)`\n    1. `onShellReady()`\n    1. `onAllReady()` and start piping\n    1. stream closed with no error\n    1. writes static html:\n    ```html\n    \u003c!DOCTYPE html\u003e\n    \u003chtml\u003e\n      \u003chead\u003e\u003c/head\u003e\n      \u003cbody\u003e\n        \u003c!--$!--\u003e\n        \u003cp\u003eLoading\u003c/p\u003e\n        \u003c!--/$--\u003e\n      \u003c/body\u003e\n    \u003c/html\u003e\n    ```\n- When content suspends on a resource that errors\n  - ✅ Client-side JavaScript\n    1. `onShellReady()` and start piping\n    1. `onError(error)`\n    1. `onAllReady()`\n    1. stream closed with no error\n    1. writes html with `\u003cscript\u003e`:\n    ```html\n    \u003c!DOCTYPE html\u003e\n    \u003chtml\u003e\n      \u003chead\u003e\u003c/head\u003e\n      \u003cbody\u003e\n        \u003c!--$?--\u003e\u003ctemplate id=\"B:0\"\u003e\u003c/template\u003e\n        \u003cp\u003eLoading\u003c/p\u003e\n        \u003c!--/$--\u003e\n      \u003c/body\u003e\n    \u003c/html\u003e\n    \u003cscript\u003e\n      function $RX(a) {\n        if ((a = document.getElementById(a)))\n          (a = a.previousSibling),\n            (a.data = \"$!\"),\n            a._reactRetry \u0026\u0026 a._reactRetry();\n      }\n      $RX(\"B:0\");\n    \u003c/script\u003e\n    ```\n  - ❌ No client-side JavaScript\n    1. `onShellReady()`\n    1. `onError(error)`\n    1. `onAllReady()` and start piping\n    1. stream closed with no error\n    1. writes static html:\n    ```html\n    \u003c!DOCTYPE html\u003e\n    \u003chtml\u003e\n      \u003chead\u003e\u003c/head\u003e\n      \u003cbody\u003e\n        \u003c!--$!--\u003e\n        \u003cp\u003eLoading\u003c/p\u003e\n        \u003c!--/$--\u003e\n      \u003c/body\u003e\n    \u003c/html\u003e\n    ```\n\n---\n\n## TODO\n\n- Add Error Boundary and see how that changes behavior\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Froyalicing%2Frendertopipeablestreamplayground","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Froyalicing%2Frendertopipeablestreamplayground","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Froyalicing%2Frendertopipeablestreamplayground/lists"}