{"_id":"@donnercody/react-hydration-on-demand","name":"@donnercody/react-hydration-on-demand","dist-tags":{"latest":"2.1.0"},"versions":{"2.1.0":{"name":"@donnercody/react-hydration-on-demand","version":"2.1.0","description":"Hydrate your React components only when you need to (with react 18+)","main":"dist/index.js","scripts":{"test":"jest","build":"babel src --out-file dist/index.js"},"repository":{"type":"git","url":"git+https://github.com/donnercody/react-hydration-on-demand.git"},"keywords":["react","hydrate","hydration","ssr","progressive","on-demand"],"publishConfig":{"access":"public"},"author":{"name":"donnercody","url":"valcol before"},"license":"MIT","bugs":{"url":"https://github.com/donnercody/react-hydration-on-demand/issues"},"homepage":"https://github.com/donnercody/react-hydration-on-demand#readme","peerDependencies":{"react":"^16.8.0 || ^17.0.0 || ^18.0.0","react-dom":"^16.8.0 || ^17.0.0 || ^18.0.0"},"devDependencies":{"@babel/cli":"^7.10.1","@babel/core":"^7.10.2","@babel/plugin-transform-runtime":"^7.10.1","@babel/preset-env":"^7.10.2","@babel/preset-react":"^7.10.1","@testing-library/dom":"^9.3.3","@testing-library/react":"^14.1.2","babel-jest":"^26.6.2","eslint":"^7.2.0","eslint-config-airbnb-base":"^14.2.0","eslint-plugin-import":"^2.21.2","jest":"^26.6.2","react":"^18.2.0","react-dom":"^18.2.0","react-test-renderer":"^18.2.0"},"dependencies":{"@babel/runtime":"^7.10.2","exenv":"^1.2.2"},"gitHead":"8617bf6c2e66e3d7c700479b6a4e52aadd456428","_id":"@donnercody/react-hydration-on-demand@2.1.0","_nodeVersion":"18.16.0","_npmVersion":"9.5.1","dist":{"integrity":"sha512-yOBGe+Xf2ApmpN6e0eKIQ8NIXqFlC24wd7OMsnnrmJ+bTQ9FsLamP6NbL8BKiViGRs8vPld62ECX22j5wpOHfg==","shasum":"909293f495f6013e9a675958835f350183a2ca39","tarball":"https://registry.npmjs.org/@donnercody/react-hydration-on-demand/-/react-hydration-on-demand-2.1.0.tgz","fileCount":4,"unpackedSize":20455,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDJH0Lgdifb28hhJhACcj+wdkgiXrTv9TviEVAqtbizeQIhAPomA83de0/S6289rEocdToRX7vny2W+1cuDyviGH1sF"}]},"_npmUser":{"name":"donnercody","email":"thoren.lederer@gmail.com"},"directories":{},"maintainers":[{"name":"donnercody","email":"thoren.lederer@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/react-hydration-on-demand_2.1.0_1701700410085_0.7424228868479104"},"_hasShrinkwrap":false}},"time":{"created":"2023-12-04T14:33:29.993Z","2.1.0":"2023-12-04T14:33:30.264Z","modified":"2023-12-04T14:33:30.561Z"},"maintainers":[{"name":"donnercody","email":"thoren.lederer@gmail.com"}],"description":"Hydrate your React components only when you need to (with react 18+)","homepage":"https://github.com/donnercody/react-hydration-on-demand#readme","keywords":["react","hydrate","hydration","ssr","progressive","on-demand"],"repository":{"type":"git","url":"git+https://github.com/donnercody/react-hydration-on-demand.git"},"author":{"name":"donnercody","url":"valcol before"},"bugs":{"url":"https://github.com/donnercody/react-hydration-on-demand/issues"},"license":"MIT","readme":"<div align=\"center\">\r\n  <h1>\r\n    <br/>\r\n    <br/>\r\n    💧\r\n    <br />\r\n    react-hydration-on-demand\r\n    <br />\r\n    <br />\r\n    <br />\r\n  </h1>\r\n  <sup>\r\n    <br />\r\n    <br />\r\n    <a href=\"https://www.npmjs.com/package/react-hydration-on-demand\">\r\n       <img src=\"https://img.shields.io/npm/dm/react-hydration-on-demand\" alt=\"npm package\" />\r\n    </a>\r\n    <a href=\"https://www.npmjs.com/package/react-hydration-on-demand\">\r\n       <img src=\"https://img.shields.io/github/actions/workflow/status/valcol/react-hydration-on-demand/main.yml\" alt=\"npm package\" />\r\n    </a>\r\n    <a href=\"https://www.npmjs.com/package/react-hydration-on-demand\">\r\n       <img src=\"https://img.shields.io/bundlephobia/minzip/react-hydration-on-demand\" alt=\"dep size\" />\r\n    </a>\r\n    <a href=\"https://www.npmjs.com/package/react-hydration-on-demand\">\r\n      <img src=\"https://img.shields.io/npm/v/react-hydration-on-demand\" alt=\"version\" />\r\n    </a>\r\n    <br />\r\n  </sup>\r\n   <h3>Hydrate your React components only when needed.<h3>\r\n  <br />\r\n  <br />\r\n  <pre>npm i <a href=\"https://www.npmjs.com/package/react-hydration-on-demand\">react-hydration-on-demand</a></pre>\r\n  <pre>yarn add <a href=\"https://www.npmjs.com/package/react-hydration-on-demand\">react-hydration-on-demand</a></pre>\r\n  <br /> \r\n  <br />\r\n</div>\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\", () => 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(() => import(\"../Card\"));\r\nconst CardWithHydrationOnDemand = withHydrationOnDemand({\r\n    on: [[\"scroll\", () => 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 <CardWithHydrationOnDemand title=\"my card\" />;\r\n    }\r\n}\r\n```\r\n\r\n> ### What if my component is also used client side only ?\r\n>\r\n> 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\", () => 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> 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(() => 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```js\r\nimport withHydrationOnDemand from \"react-hydration-on-demand\";\r\nimport Card from \"../Card\";\r\n\r\nconst CardWithHydrationOnDemand = withHydrationOnDemand({ on: [\"delay\"] })(\r\n    Card\r\n);\r\n\r\nexport default class App extends React.Component {\r\n    render() {\r\n        return (\r\n            <CardWithHydrationOnDemand\r\n                title=\"my card\"\r\n                wrapperProps={{\r\n                    className: \"customClassName\",\r\n                    style: { display: \"contents\" },\r\n                }}\r\n            />\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","readmeFilename":"README.md"}