{"id":42287593,"url":"https://github.com/valcol/react-hydration-on-demand","last_synced_at":"2026-01-27T09:23:06.236Z","repository":{"id":40592499,"uuid":"230811295","full_name":"valcol/react-hydration-on-demand","owner":"valcol","description":"Hydrate your React components only when you need to.","archived":false,"fork":false,"pushed_at":"2025-07-22T04:59:19.000Z","size":1720,"stargazers_count":197,"open_issues_count":4,"forks_count":12,"subscribers_count":4,"default_branch":"master","last_synced_at":"2025-10-10T09:38:05.088Z","etag":null,"topics":["code-splitting","fid","hydration","progressive-hydration","react","render","ssr","tti"],"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/valcol.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","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,"publiccode":null,"codemeta":null}},"created_at":"2019-12-29T22:37:15.000Z","updated_at":"2025-10-09T10:25:38.000Z","dependencies_parsed_at":"2023-02-10T22:15:42.152Z","dependency_job_id":"6ccb83a0-c84b-462b-8f48-2d8831f60a9b","html_url":"https://github.com/valcol/react-hydration-on-demand","commit_stats":{"total_commits":37,"total_committers":5,"mean_commits":7.4,"dds":0.4864864864864865,"last_synced_commit":"07cc7751aa9fdaf628c6543437cbfc75ab242287"},"previous_names":[],"tags_count":4,"template":false,"template_full_name":null,"purl":"pkg:github/valcol/react-hydration-on-demand","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/valcol%2Freact-hydration-on-demand","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/valcol%2Freact-hydration-on-demand/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/valcol%2Freact-hydration-on-demand/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/valcol%2Freact-hydration-on-demand/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/valcol","download_url":"https://codeload.github.com/valcol/react-hydration-on-demand/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/valcol%2Freact-hydration-on-demand/sbom","scorecard":{"id":914925,"data":{"date":"2025-08-11","repo":{"name":"github.com/valcol/react-hydration-on-demand","commit":"f179ce4d1c879b67d2496111848770101b4a1a87"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":4.6,"checks":[{"name":"Maintained","score":0,"reason":"0 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"Dangerous-Workflow","score":10,"reason":"no dangerous workflow patterns detected","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"Code-Review","score":0,"reason":"Found 0/18 approved changesets -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"Token-Permissions","score":9,"reason":"detected GitHub workflow tokens with excessive permissions","details":["Info: jobLevel 'contents' permission set to 'read': .github/workflows/main.yml:12","Warn: no topLevel permission defined: .github/workflows/main.yml:1","Info: no jobLevel write permissions found"],"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"Pinned-Dependencies","score":3,"reason":"dependency not pinned by hash detected -- score normalized to 3","details":["Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/main.yml:15: update your workflow using https://app.stepsecurity.io/secureworkflow/valcol/react-hydration-on-demand/main.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/main.yml:16: update your workflow using https://app.stepsecurity.io/secureworkflow/valcol/react-hydration-on-demand/main.yml/master?enable=pin","Info:   0 out of   2 GitHub-owned GitHubAction dependencies pinned","Info:   1 out of   1 npmCommand dependencies pinned"],"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Info: FSF or OSI recognized license: MIT License: LICENSE:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Packaging","score":10,"reason":"packaging workflow detected","details":["Info: Project packages its releases by way of GitHub Actions.: .github/workflows/main.yml:9"],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"Branch-Protection","score":0,"reason":"branch protection not enabled on development/release branches","details":["Warn: branch protection not enabled for branch 'master'"],"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}},{"name":"SAST","score":0,"reason":"SAST tool is not run on all commits -- score normalized to 0","details":["Warn: 0 commits out of 12 are checked with a SAST tool"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}},{"name":"Vulnerabilities","score":8,"reason":"2 existing vulnerabilities detected","details":["Warn: Project is vulnerable to: GHSA-v6h2-p8h4-qcjw","Warn: Project is vulnerable to: GHSA-fjxv-7rqg-78g4"],"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}}]},"last_synced_at":"2025-08-24T20:37:15.665Z","repository_id":40592499,"created_at":"2025-08-24T20:37:15.665Z","updated_at":"2025-08-24T20:37:15.665Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28810483,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-27T07:41:26.337Z","status":"ssl_error","status_checked_at":"2026-01-27T07:41:08.776Z","response_time":168,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"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":["code-splitting","fid","hydration","progressive-hydration","react","render","ssr","tti"],"created_at":"2026-01-27T09:23:05.632Z","updated_at":"2026-01-27T09:23:06.221Z","avatar_url":"https://github.com/valcol.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cdiv align=\"center\"\u003e\r\n  \u003ch1\u003e\r\n    \u003cbr/\u003e\r\n    \u003cbr/\u003e\r\n    💧\r\n    \u003cbr /\u003e\r\n    react-hydration-on-demand\r\n    \u003cbr /\u003e\r\n    \u003cbr /\u003e\r\n    \u003cbr /\u003e\r\n  \u003c/h1\u003e\r\n  \u003csup\u003e\r\n    \u003cbr /\u003e\r\n    \u003cbr /\u003e\r\n    \u003ca href=\"https://www.npmjs.com/package/react-hydration-on-demand\"\u003e\r\n       \u003cimg src=\"https://img.shields.io/npm/dm/react-hydration-on-demand\" alt=\"npm package\" /\u003e\r\n    \u003c/a\u003e\r\n    \u003ca href=\"https://www.npmjs.com/package/react-hydration-on-demand\"\u003e\r\n       \u003cimg src=\"https://img.shields.io/github/actions/workflow/status/valcol/react-hydration-on-demand/main.yml\" alt=\"npm package\" /\u003e\r\n    \u003c/a\u003e\r\n    \u003ca href=\"https://www.npmjs.com/package/react-hydration-on-demand\"\u003e\r\n       \u003cimg src=\"https://img.shields.io/bundlephobia/minzip/react-hydration-on-demand\" alt=\"dep size\" /\u003e\r\n    \u003c/a\u003e\r\n    \u003ca href=\"https://www.npmjs.com/package/react-hydration-on-demand\"\u003e\r\n      \u003cimg src=\"https://img.shields.io/npm/v/react-hydration-on-demand\" alt=\"version\" /\u003e\r\n    \u003c/a\u003e\r\n    \u003cbr /\u003e\r\n  \u003c/sup\u003e\r\n   \u003ch3\u003eHydrate your React components only when needed.\u003ch3\u003e\r\n  \u003cbr /\u003e\r\n  \u003cbr /\u003e\r\n  \u003cpre\u003enpm i \u003ca href=\"https://www.npmjs.com/package/react-hydration-on-demand\"\u003ereact-hydration-on-demand\u003c/a\u003e\u003c/pre\u003e\r\n  \u003cpre\u003eyarn add \u003ca href=\"https://www.npmjs.com/package/react-hydration-on-demand\"\u003ereact-hydration-on-demand\u003c/a\u003e\u003c/pre\u003e\r\n  \u003cbr /\u003e \r\n  \u003cbr /\u003e\r\n\u003c/div\u003e\r\n\r\n[![Edit react-hydration-on-demand](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/p/sandbox/stoic-sinoussi-64wys6)\r\n\r\nHydrates server-side rendered components only when necessary to offload the main thread, improving TTI, TBT, and FID.\r\nIt can be used with code-splitting libraries to load component code at runtime just before the hydration step, reducing the initial payload size of your application.\r\n\r\n![](reactrender.png?raw=true)\r\n\r\n## How to use\r\n\r\n```js\r\nimport withHydrationOnDemand from \"react-hydration-on-demand\";\r\nimport Card from \"../Card\";\r\n\r\n//Hydrate when the component enters the viewport\r\nconst CardWithHydrationOnDemand = withHydrationOnDemand({ on: [\"visible\"] })(\r\n    Card\r\n);\r\n\r\n//Hydrate when the browser's event loop is idle\r\nconst CardWithHydrationOnDemand = withHydrationOnDemand({ on: [\"idle\"] })(Card);\r\n\r\n//Hydrate after a delay (by default: 2000ms)\r\nconst CardWithHydrationOnDemand = withHydrationOnDemand({ on: [\"delay\"] })(\r\n    Card\r\n);\r\n\r\n//Hydrate after a custom delay (3000ms)\r\nconst CardWithHydrationOnDemand = withHydrationOnDemand({\r\n    on: [[\"delay\", 3000]],\r\n})(Card);\r\n\r\n//Hydrate when the user scroll on the document\r\nconst CardWithHydrationOnDemand = withHydrationOnDemand({\r\n    on: [[\"scroll\", () =\u003e document]],\r\n})(Card);\r\n\r\n//Hydrate when the when the browser's event loop is idle or when the user scroll, whichever comes first\r\nconst CardWithHydrationOnDemand = withHydrationOnDemand({\r\n    on: [\"idle\", \"visible\"],\r\n})(Card);\r\n\r\n//Load an async chunck before hydration\r\nimport loadable from \"@loadable/component\";\r\n\r\nconst LoadableCard = loadable(() =\u003e import(\"../Card\"));\r\nconst CardWithHydrationOnDemand = withHydrationOnDemand({\r\n    on: [[\"scroll\", () =\u003e document]],\r\n    onBefore: LoadableCard.load,\r\n})(LoadableCard);\r\n\r\n//Never hydrate unless the prop forceHydration is set to true\r\nconst CardWithHydrationOnDemand = withHydrationOnDemand()(Card);\r\n\r\n//...\r\n\r\nexport default class App extends React.Component {\r\n    render() {\r\n        return \u003cCardWithHydrationOnDemand title=\"my card\" /\u003e;\r\n    }\r\n}\r\n```\r\n\r\n\u003e ### What if my component is also used client side only ?\r\n\u003e\r\n\u003e If the component isn't rendered server side, it will render directly and behave normally.\r\n\r\n## Options\r\n\r\n### `on: Array`\r\n\r\nAn array of events who will trigger the hydration.\r\nCan contains event names directly or as an array of `['event name', options]`.\r\n\r\n```js\r\nimport withHydrationOnDemand from \"react-hydration-on-demand\";\r\nimport Card from \"../Card\";\r\n\r\nconst CardWithHydrationOnDemand = withHydrationOnDemand({\r\n    on: [\"visible\", [\"scroll\", () =\u003e document], [\"delay\", 5000]],\r\n})(Card);\r\n```\r\n\r\nSupport [all DOM events](https://developer.mozilla.org/en-US/docs/Web/Events) and more :\r\n\r\n| Event name                                                                | Options                                                                                                                                                                 | Description                                                                                                                    |\r\n| ------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------ |\r\n| [**all DOM events**](https://developer.mozilla.org/en-US/docs/Web/Events) | `getTarget: Function` who return the event target (default: the wrapped component)                                                                                      |\r\n| **delay**                                                                 | `delay: Number` in ms (default value: 2000)                                                                                                                             | Scheduled hydration.                                                                                                           |\r\n| **visible**                                                               | `getOptions: Function` who return an [intersectionObserver options](https://developer.mozilla.org/en-US/docs/Web/API/IntersectionObserver) object (default: no options) | Requires IntersectionObserver. **Polyfill not included.** If unsupported the component is directy hydrated.                    |\r\n| **idle**                                                                  |                                                                                                                                                                         | Requires requestIdleCallback. **Polyfill not included.** If unsupported the component will be hydrated with a delay of 2000ms. |\r\n\r\n### `onBefore: Promise` (optional)\r\n\r\nPromise to resolve before hydration.\r\n\r\n\u003e Can be usefull if you need to preload chunks before hydration for example.\r\n\r\n```js\r\nimport withHydrationOnDemand from \"react-hydration-on-demand\";\r\nimport loadable from \"@loadable/component\";\r\n\r\nconst LoadableCard = loadable(() =\u003e import(\"../Card\"));\r\nconst CardWithHydrationOnDemand = withHydrationOnDemand({\r\n    on: [\"visible\"],\r\n    onBefore: LoadableCard.load,\r\n})(LoadableCard);\r\n```\r\n\r\n### `whenInputPending: Boolean` (optional, default: false)\r\n\r\nWhen set to true use `navigator.scheduling.isInputPending` to check if there is a pending user input on mount. If that's the case, hydration will be delayed using the strategies defined in the `on` option to allow the browser to handle the user input.\r\nIf there is no pending input, the component will be hydrated directly to be interactive as fast as possible.\r\n\r\nSee https://github.com/WICG/is-input-pending for more infos.\r\n\r\n### `isInputPendingFallbackValue: Boolean` (optional, default: true)\r\n\r\nThe default value returned on browsers who don't implements `navigator.scheduling.isInputPending` when `whenInputPending` set to true.\r\n\r\n### `disableFallback: Boolean` (optional, default: false)\r\n\r\nIf set at true the component will not be rendered client side if not rendered server side.\r\n\r\n## Props\r\n\r\n### `wrapperProps: Object` (optional)\r\n\r\nProps that are applied to the div which wraps the provided component.\r\n\r\n#### `wrapperProps.as: String | React.ComponentType` (optional, default: 'section')\r\n\r\nSpecifies the HTML element or React component to use as the wrapper. This allows for semantically correct and accessible markup. For example, use `'div'` for generic containers or `'a'` for links.\r\n\r\n```js\r\nimport withHydrationOnDemand from \"react-hydration-on-demand\";\r\nimport Card from \"../Card\";\r\n\r\nconst CardWithHydrationOnDemand = withHydrationOnDemand({ on: [\"delay\"] })(Card);\r\n\r\nexport default class App extends React.Component {\r\n    render() {\r\n        return (\r\n            \u003cCardWithHydrationOnDemand\r\n                title=\"my card\"\r\n                wrapperProps={{\r\n                    as: 'div', // Use a div instead of the default section\r\n                    className: \"customClassName\",\r\n                    style: { display: \"contents\" },\r\n                }}\r\n            /\u003e\r\n        );\r\n    }\r\n}\r\n```\r\n\r\n### `forceHydration: Boolean` (optional, default: false)\r\n\r\nForce the hydration of the component.\r\n\r\n## Playground \u0026 Bug Reproduction\r\n\r\nYou can use the following CodeSandbox to try out the library or reproduce bugs. When creating a new issue, please fork this sandbox and include the link in your bug report to help me understand and fix the problem more efficiently.\r\n\r\n[![Edit react-hydration-on-demand](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/p/sandbox/stoic-sinoussi-64wys6)\r\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fvalcol%2Freact-hydration-on-demand","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fvalcol%2Freact-hydration-on-demand","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fvalcol%2Freact-hydration-on-demand/lists"}