{"id":13472434,"url":"https://github.com/FormidableLabs/react-ssr-prepass","last_synced_at":"2025-03-26T15:32:16.586Z","repository":{"id":37663862,"uuid":"175187015","full_name":"FormidableLabs/react-ssr-prepass","owner":"FormidableLabs","description":"A custom partial React SSR renderer for prefetching and suspense","archived":false,"fork":false,"pushed_at":"2024-11-05T21:23:06.000Z","size":647,"stargazers_count":602,"open_issues_count":9,"forks_count":26,"subscribers_count":48,"default_branch":"master","last_synced_at":"2025-03-12T21:03:17.837Z","etag":null,"topics":["react","react-dom","server-side-rendering"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/FormidableLabs.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2019-03-12T10:25:13.000Z","updated_at":"2025-03-09T18:25:39.000Z","dependencies_parsed_at":"2024-06-18T12:27:16.443Z","dependency_job_id":"dd63f0a6-47ae-4fcc-9bfb-b6295a4ee861","html_url":"https://github.com/FormidableLabs/react-ssr-prepass","commit_stats":{"total_commits":121,"total_committers":8,"mean_commits":15.125,"dds":0.09917355371900827,"last_synced_commit":"099119761074dc35d2bc0d884297e6c84c77f684"},"previous_names":[],"tags_count":18,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/FormidableLabs%2Freact-ssr-prepass","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/FormidableLabs%2Freact-ssr-prepass/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/FormidableLabs%2Freact-ssr-prepass/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/FormidableLabs%2Freact-ssr-prepass/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/FormidableLabs","download_url":"https://codeload.github.com/FormidableLabs/react-ssr-prepass/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":245681466,"owners_count":20655202,"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":["react","react-dom","server-side-rendering"],"created_at":"2024-07-31T16:00:54.598Z","updated_at":"2025-03-26T15:32:16.153Z","avatar_url":"https://github.com/FormidableLabs.png","language":"JavaScript","funding_links":[],"categories":["JavaScript","📦 Legacy \u0026 Inactive Projects"],"sub_categories":[],"readme":"# react-ssr-prepass\n\n\u003cp\u003e\n  \u003ca href=\"https://travis-ci.com/FormidableLabs/react-ssr-prepass\"\u003e\n    \u003cimg alt=\"Build Status\" src=\"https://travis-ci.com/FormidableLabs/react-ssr-prepass.svg?branch=master\" /\u003e\n  \u003c/a\u003e\n  \u003ca href=\"https://codecov.io/gh/FormidableLabs/react-ssr-prepass\"\u003e\n    \u003cimg alt=\"Test Coverage\" src=\"https://codecov.io/gh/FormidableLabs/react-ssr-prepass/branch/master/graph/badge.svg\" /\u003e\n  \u003c/a\u003e\n  \u003ca href=\"https://npmjs.com/package/react-ssr-prepass\"\u003e\n    \u003cimg alt=\"NPM Version\" src=\"https://img.shields.io/npm/v/react-ssr-prepass.svg\" /\u003e\n  \u003c/a\u003e\n  \u003ca href=\"https://github.com/FormidableLabs/react-ssr-prepass#maintenance-status\"\u003e\n    \u003cimg alt=\"Maintenance Status\" src=\"https://img.shields.io/badge/maintenance-experimental-blueviolet.svg\" /\u003e\n  \u003c/a\u003e\n\u003c/p\u003e\n\n\u003cp\u003e\n  \u003ccode\u003ereact-dom/server\u003c/code\u003e does not have support for suspense yet.\u003cbr /\u003e\n  \u003ccode\u003ereact-ssr-prepass\u003c/code\u003e offers suspense on the server-side today, until it does. ✨\n\u003c/p\u003e\n\n`react-ssr-prepass` is a **partial server-side React renderer** that does a prepass\non a React element tree and suspends when it finds thrown promises. It also\naccepts a visitor function that can be used to suspend on anything.\n\nYou can use it to fetch data before your SSR code calls `renderToString` or\n`renderToNodeStream`.\n\n\u003e ⚠️ **Note:** Suspense is unstable and experimental. This library purely\n\u003e exists since `react-dom/server` does not support data fetching or suspense\n\u003e yet. This two-pass approach should just be used until server-side suspense\n\u003e support lands in React.\n\n## The Why \u0026 How\n\nIt's quite common to have some data that needs to be fetched before\nserver-side rendering and often it's inconvenient to specifically call\nout to random fetch calls to get some data. Instead **Suspense**\noffers a practical way to automatically fetch some required data,\nbut is currently only supported in client-side React.\n\n`react-ssr-prepass` offers a solution by being a \"prepass\" function\nthat walks a React element tree and executing suspense. It finds all\nthrown promises (a custom visitor can also be provided) and waits for\nthose promises to resolve before continuing to walk that particular\nsuspended subtree. Hence, it attempts to offer a practical way to\nuse suspense and complex data fetching logic today.\n\nA two-pass React render is already quite common for in other libraries\nthat do implement data fetching. This has however become quite impractical.\nWhile it was trivial to previously implement a primitive React renderer,\nthese days a lot more moving parts are involved to make such a renderer\ncorrect and stable. This is why some implementations now simply rely\non calling `renderToStaticMarkup` repeatedly.\n\n`react-ssr-prepass` on the other hand is a custom implementation\nof a React renderer. It attempts to stay true and correct to the\nReact implementation by:\n\n- Mirroring some of the implementation of `ReactPartialRenderer`\n- Leaning on React elements' symbols from `react-is`\n- Providing only the simplest support for suspense\n\n## Quick Start Guide\n\nFirst install `react-ssr-prepass` alongside `react` and `react-dom`:\n\n```sh\nyarn add react-ssr-prepass\n# or\nnpm install --save react-ssr-prepass\n```\n\nIn your SSR code you may now add it in front of your usual `renderToString`\nor `renderToNodeStream` code:\n\n```js\nimport { createElement } from 'react'\nimport { renderToString } from 'react-dom/server'\n\nimport ssrPrepass from 'react-ssr-prepass'\n\nconst renderApp = async (App) =\u003e {\n  const element = createElement(App)\n  await ssrPrepass(element)\n\n  return renderToString(element)\n}\n```\n\nAdditionally you can also pass a \"visitor function\" as your second argument.\nThis function is called for every React class or function element that is\nencountered.\n\n```js\nssrPrepass(\u003cApp /\u003e, (element, instance) =\u003e {\n  if (element.type === SomeData) {\n    return fetchData()\n  } else if (instance \u0026\u0026 instance.fetchData) {\n    return instance.fetchData()\n  }\n})\n```\n\nThe first argument of the visitor is the React element. The second is\nthe instance of a class component or undefined. When you return\na promise from this function `react-ssr-prepass` will suspend before\nrendering this element.\n\nYou should be aware that `react-ssr-prepass` does not handle any\ndata rehydration. In most cases it's fine to collect data from your cache\nor store after running `ssrPrepass`, turn it into JSON, and send it\ndown in your HTML result.\n\n## Prior Art\n\nThis library is (luckily) not a reimplementation from scratch of\nReact's server-side rendering. Instead it's mostly based on\nReact's own server-side rendering logic that resides in its\n[`ReactPartialRenderer`](https://github.com/facebook/react/blob/13645d2/packages/react-dom/src/server/ReactPartialRenderer.js).\n\nThe approach of doing an initial \"data fetching pass\" is inspired by:\n\n- [`react-apollo`'s `getDataFromTree`](https://github.com/apollographql/react-apollo/blob/master/src/getDataFromTree.ts)\n- [`react-tree-walker`](https://github.com/ctrlplusb/react-tree-walker)\n\n## Maintenance Status\n\n**Experimental:** This project is quite new. We're not sure what our ongoing maintenance plan for this project will be. Bug reports, feature requests and pull requests are welcome. If you like this project, let us know!\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FFormidableLabs%2Freact-ssr-prepass","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FFormidableLabs%2Freact-ssr-prepass","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FFormidableLabs%2Freact-ssr-prepass/lists"}