{"bin":{"imported-components":"./bin/imported-components"},"bugs":{"url":"https://github.com/theKashey/react-hot-component-loader/issues"},"dist":{"shasum":"fc463a9fa688abb803e39cc8ffd96cb08c6710e3","tarball":"https://registry.npmjs.org/react-imported-component/-/react-imported-component-6.0.0-beta.2.tgz","fileCount":89,"integrity":"sha512-XOXoeUyfnb7XrXxcXnLqU13XrFVNB/WDBRvnAobDBKD/XA7N8qY/GVr+7F+1TfD1oFKNpRK3JrEgYuBkVXD60A==","signatures":[{"sig":"MEUCIQDzDFmea0LQ9Tp63qGEv5db9bblVyjuASTZhP1BGt9WqAIgTv0dkID8MnyzWk4hFvIC8hzd2wKWkA+ueOdsmbN/gHM=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":101524,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdYiiyCRA9TVsSAnZWagAAdpQP+wX949XFUa0WlfDDwMaH\nR4LkJ+9xcfX74INzK3TJ9J23PJqKQh4bQwMA+fQBGzxKp4TWZbpjygTjfxma\nulGVtdvZs6pXmCNMG5h3VPAARcVVTtFH49gobZqxvfJOJDaECzos/3QZrrgS\nOyH7gHx+OFiFT7NS16QdAsalKik9WexkK6DZ/WtMHn2JeWKPNrI1XUl0SjwN\njQ7KrzNeR7RrRgtiGDAJGMenDMGmgr1j7t9E3Hpsup4RtyXgHT/Lo6NeeDoD\nHvfGP/0m3rrS+RM9/v1XHSdv2+xuHW/AgDOJicR0yuk9iCeYOKqzoMkJ0XYl\n3xr470vlT9j999JiInu7YVjQ2Wu2OyrIdKns/Apqcsb9z5VqlBZox6rNm0el\nChSPKmIzaoaX9FXxbNMRi4d06tZE/itUES1sgRUA7IMDAPxU2DTPrpIryk7V\nr7oclctGTXh95cjIa/SRUnTJjWxLQ+coM82iwuYOZ9dErQ8eW8EQ3rXvYcVi\nyhm7Ntsh/kKJxsdqy2nO9fVHhrOAGCCQzijUxFx9vgK8Qe/k94YAX3ZryHFO\nKKonzdF7a4E9/y6SSRdOZ+iSIi190WkOKTi4RCwyVnDJy3qadk9T9YIhoLqk\n5iSnu4SrIriAMG2FURSXhvOyc5puI899Hgtr3JbVLJzdh+u+ZRZAlz4gYHRs\nVHQ1\r\n=OhtM\r\n-----END PGP SIGNATURE-----\r\n"},"main":"dist/es5/index.js","name":"react-imported-component","types":"dist/es5/index.d.ts","author":{"name":"theKashey","email":"thekashey@gmail.com"},"module":"dist/es2015/index.js","readme":"<div align=\"center\">\n  <h1>IMPORTED COMPONENT ✂</h1>\n  <br/>\n  <img src=\"./assets/imported-logo.png\" alt=\"imported components\" width=\"409\" align=\"center\">\n  <br/>\n  <br/>\n   SSR-friendly code splitting compatible with any platform.\n  <br/>\n   Deliver a better experience within a single import.\n  <br/>\n  <br/>\n  \n  <a href=\"https://www.npmjs.com/package/react-imported-component\">\n    <img src=\"https://img.shields.io/npm/v/react-imported-component.svg?style=flat-square\" />\n  </a>\n    \n  <a href=\"https://circleci.com/gh/theKashey/react-imported-component/tree/master\">\n   <img src=\"https://img.shields.io/circleci/project/github/theKashey/react-imported-component/master.svg?style=flat-square)\" alt=\"Build status\">\n  </a> \n\n  <a href=\"https://www.npmjs.com/package/react-imported-component\">\n   <img src=\"https://img.shields.io/npm/dm/react-imported-component.svg\" alt=\"npm downloads\">\n  </a> \n\n  <a href=\"https://bundlephobia.com/result?p=react-imported-component\">\n   <img src=\"https://img.shields.io/bundlephobia/minzip/react-imported-component.svg\" alt=\"bundle size\">\n  </a> \n\n  <img src=\"https://badges.greenkeeper.io/theKashey/react-imported-component.svg\" />\n    \n  <br/>\n</div>\n\n👉 [Usage](#usage)  |  [API](#api)  | [SSR](#ssr)  |  [Concurrent loading](#concurrent-loading) \n\n \nKey features:\n - 1️⃣ Single source of truth - your __bundler drives__ everything.\n - 📖 __library__ level code __splitting__\n - 🧙️ Hybrid and __Prerendering__ compatible\n - 💡 __TypeScript__ bindings\n - ⚛️ __React.Lazy__ underneath (if hot module updates are disabled)\n - 🌟 Async on client, sync on server. Supports __Suspense__ (even on server side)\n - 📦 could work with __any bundler__ - webpack, rollup, parcel or puppeteer - it does not matter \n \n Other features:\n - 🔥 Hot-Module-Replacement/React-Hot-Loader friendly\n - ⛓️ support forwardRef\n - ⚛️ Rect 16/Async/Hooks ready\n - 🛠 HOC, Component, Hooks API\n - 🐳 stream rendering support\n - 👥 partial hydration out of the box\n - 📦 and yes - this is the only __parcel-bundler compatible__ SSR-friendly React code splitting library\n \n 👍 Better than [React.Lazy](https://reactjs.org/docs/code-splitting.html#reactlazy):\n - It __IS__ Lazy, just with some stuff around*\n - SSR, Prerendering and Preloading support.\n - With or without Suspense, and easier Error cases support.\n \n 👍 Better than [Loadable-Component](https://github.com/smooth-code/loadable-components):\n - Not bound to webpack.\n - Easy way to use per-browser(modern/legacy) bundles.\n - Strong typing.\n - Prerendering support\n \n 👌 Not as good with\n - Loads chunks only after the `main one`, as long as loader code is bundled inside the main chunk, so it should be loaded first.\n - Not an issue with the `progressive hydration`, and might provide a better UX via feature detection.\n - Provides 👨‍🔬 technological workaround - [see here](#concurrent-loading)\n    \n<a name=\"usage\"/>\n\n# Usage\n\n## Server side\nJust a proper setup and a bit of magic\n\n## Client side\n\n### Component\n`imported` provides 2 common ways to define a component, which are more different inside than outside \n\n- using `pre-lazy` API.\n```javascript\nimport importedComponent from 'react-imported-component';\nconst Component = importedComponent( () => import('./Component'));\n\nconst Component = importedComponent( () => import('./Component'), {\n  LoadingComponent: Spinner, // what to display during the loading\n  ErrorComponent: FatalError // what to display in case of error\n});\n\nComponent.preload(); // force preload\n\n// render it\n<Component... />\n```\n\n- using `lazy` API. It's almost the same `React.lazy` outside, and exactly the same inside.\n```js\nimport {lazy, LazyBoundary} from 'react-imported-component'\nconst Component = lazy(() => import('./Component'));\n\nconst ClientSideOnly = () => (\n    <Suspense>\n     <Component />\n    </Suspense> \n);\n\n// or let's make it SSR friendly\nconst ServerSideFriendly = () => (\n    <LazyBoundary> // LazyBoundary is Suspense on the client, and \"nothing\" on the server\n      <Component />\n    </LazyBoundary> \n)\n```\n`LazyBoundary` is a `Suspense` on Client Side, and `React.Fragment` on Server Side. Don't forget - \"dynamic\" imports are sync on a server.\n\nExample: [React.lazy vs Imported-component](https://codesandbox.io/s/wkl95r0qw8)\n\n### Hook\nHowever, you may not load only components - you may load anything\n```js\nimport {useImported} from 'react-imported-component'\n\nconst MyCalendarComponent = () => {\n  const {\n      moment,\n      loading\n    } = useImported(() => import(\"moment\"));\n  \n  return loading ? \"...\" : <span>today is {moment(Date.now).format()}</span>\n}\n\n// or we could make it a bit more interesting...\n\nconst MyCalendarComponent = () => {\n  const {\n      imported: format  = x => \"---\", // default value is used while importing library\n    } = useImported(\n      () => import(\"moment\"), \n      moment => x => moment(x).format // masking everything behind\n    );\n  \n  return <span>today is {format(Date.now())</span>\n}\n```\nWhat you could load using `useImported`? Everything - `imported` itself is using it to import components.\n\n<a name=\"api\"/>\n\n# API\n\n### Code splitting components\n> import {*} from 'react-imported-component';\n- `importedComponent(importFunction, [options]): ComponentLoader` - main API, default export, HOC to create imported component.\n  - `importFunction - function which resolves with Component to be imported.\n  - `options` - optional settings\n  - `options.async` - activates react suspense support. Will throw a Promise in a Loading State - use it with Suspense in a same way you use __React.lazy__.\n  - `options.LoadingComponent` - component to be shown in Loading state\n  - `options.ErrorComponent` - component to be shown in Error state. Will re-throw error if ErrorComponent is not set. Use ErrorBoundary to catch it.  \n  - `options.onError` - function to consume the error, if one will thrown. Will rethrow a real error if not set.\n  - `options.exportPicker` - function to pick `not default` export from a `importFunction`\n  - `options.render(Component, state, props) `- function to render the result. Could be used to tune the rendering.  \n  \n  - [static] `.preload` - static method to preload components.\n\n- `lazy(importFunction)` - helper to mimic __React.lazy__ behavior\n\n- `useImported(importFunction, exportPicker?)` - code splitting hook\n  - `importFunction` - a function which resolves to `default` or `wildcard` import(T | {default:T})\n  - `exportPicker` - function to pick \"T\" from the import\n\n### Server side API\n> import {*} from 'react-imported-component/server';\n- `whenComponentsReady():Promise` - will be resolved, when all components are loaded. Usually on the next \"Promise\" tick.\n- `drainHydrateMarks([stream])` - returns the currently used marks, and clears the list. \n- `printDrainHydrateMarks([stream])` - print our the `drainHydrateMarks`.\n#### Stream API\n- `createLoadableStream` - creates a steam\n- `ImportedStream` - wraps another component with import usage tracker.\n- `createLoadableTransformer` - creates nodejs StreamTransformer\n- `getLoadableTrackerCallback` - helper factory for the stream transformer\n\n### Client side API\n> import {*} from 'react-imported-component/boot';\n- `whenComponentsReady():Promise`, will be resolved, when all (loading right now) marks are loaded.\n- `rehydrateMarks([marks]):Promise`, loads _marked_ async chunks.\n- `injectLoadableTracker` - helper factory for the stream transformer\n   \n# Setup\n\n## In short\n1. Add `babel` plugin\n2. Run `yarn imported-components src src/imported.js` to extract all your imports into a `run time chunk` (aka async-requires).\n3. Replace `React.lazy` with our `lazy`, and `React.Suspense` with our `LazyBoundary`.\n4. Add `printDrainHydrateMarks` to the server code code.\n5. Add `rehydrateMarks` to the client code\n6. Done. Just read the rest of readme for details.\n\nThere are examples for webpack, parcel, and react-snap. Just follow them.\n\n## 1. Configure babel plugin\n**On the server**:\n```json\n{\n  \"plugins\": [\"react-imported-component/babel\", \"babel-plugin-dynamic-import-node\"/* might be optional for babel 7*/]\n}\n```\n**On the client**:\n```json\n{\n  \"plugins\": [\"react-imported-component/babel\"]\n}\n```\nImported-Component will hook into dynamic imports, providing extra information about files you want to load.\n\n## 2. Add one more command into package.json\nCLI command `imported-components [sources ROOT] [targetFile.js]` (use .ts for TypeScript)\n```js\n \"generate-imported-component\": \"imported-components src src/imported.js\"\n```\nWhen you will execute this command - all `imports` among your codebase would be found and extracted to a file provided.\nThis will gave ability to orchestrate code-splitting later.\n\n> The current implementation will discover and use all `imports`, even // commented ones\n\n## 3. Start using `imported`, `lazy` or `useImported`\nWithout you using API provided nothing would work.\n\n## 4. Add server side tracking\nThere are two ways to do it - in a single threaded way, and async\n#### Single threaded\n```js\n  import { printDrainHydrateMarks, drainHydrateMarks } from 'react-imported-component';\n  // this action will \"drain\" all currently used(by any reason) marks\n  // AND print a script tag\n  const html = renderToString(<YourApp />) + printDrainHydrateMarks();\n  \n  // OR return list of usedmarks, and yet again CLEAR the marks list.\n  const html = renderToString(<YourApp />) + \"<script>const marks=\"+JSON.stringify(drainHydrateMarks())+\"</script>\";\n```\n#### renderToStream or async render\n```js\nimport {createLoadableStream} 'react-imported-component';\n\nlet importedStream = createLoadableStream();\n// ImportedStream is a async rendering \"provider\"\nconst stream = renderToStream(\n  <ImportedStream stream={importedStream}>\n    <YourApp />\n  </ImportedStream>\n);\n\n// you'd then pipe the stream into the response object until it's done\nstream.pipe(res, { end: false });\n\n// and finalize the response with closing HTML\nstream.on('end', () =>\n    // print marks used in the file\n    res.end(`${printDrainHydrateMarks(importedStream)}</body></html>`),\n)\n```\nHowever, the idea is just to use `streams` to separate renders\n```js\nconst html = renderToString(<ImportedStream stream={importedStream}><YourApp /></ImportedStream>) + printDrainHydrateMarks(importedStream);\n```\n\n## 5. Add `rehydrateMarks` to the client code\nBefore rendering your application you have to ensure - all parts are loaded.\n`rehydrateMarks` will load everything you need, and provide a promise to await.\n```js\n  import { rehydrateMarks } from 'react-imported-component';\n\n  // this will trigger all marked imports, and await for competition.\n  rehydrateMarks().then(() => {\n    // better\n    ReactDOM.hydrate(<App />, document.getElementById('main'));\n    // or\n    ReactDOM.render(<App />, document.getElementById('main'));\n  });\n```\n`rehydrateMarks` accepts a list of `marks` from a server side(`drainHydrateMarks`), loads all \nnecessary chunks and then resolves.\n\n<a name=\"concurrent-loading\"/>\n\n## A VERY IMPORTANT MOMENT - Concurrent Loading\nAll other code splitting libraries are working a bit differently - they amend `webpack` building process,\ngathering information about how the final chunks are assembled, and __injects the real scripts and styles__ to the server response,\nthus all scripts, used to render something on the Server would be loaded in a parallel in on Client.\nLiterally - they are defined in the HTML.\n`React-imported-component` is different, it starts \"working\" when the bundle is loaded, thus\n__loading of chunks is deferred__. \n> In the normals conditions `react-imported-component` would be \"slower\" than a \"webpack\" library.\n\nHowever, it is not a problem, as long as (for now), script execution is single trhreaded, and even you if can load multiple scripts\nsimultaneously - you can't __run__ them in parallel*.\n\nJust change your entry point, to utilize this limitation.\n\nLet's call it - __Scheduler optimization__. \n\n#### Simply static render\n1. Split your app into `boot` and `main` parts\n2. `rehydrate` at the boot\n```js\n // index.js (boot)\n import './src/imported'; // the file generated by \"generate-imported-component\" (.2)\n import {rehydrateMarks} from 'react-imported-component/boot';\n  \n rehydrateMarks(); // just start loading what's needed\n  \n // load/execute the rest after letting the browser kick off chunk loading\n // for example wrapping it in two Promises (1ms timeout or setImmediate)\n Promise.resolve().then(() =>\n   Promise.resolve().then(() => {\n     // load the rest\n     require('./main');\n     // don't forget to `await rehydrateMarks()` before render\n   })\n );\n```\nThis will just start loading extra chunks before the main bundle got completely parsed and executed.\n\n#### Stream render\n> See examples/SSR/parcel-react-ssr/server-stream for details\n1. Add your main bundle to the `head`, using __async__ script tag. Not defer! We have to do it async\n2. Add `loadableTracker` at server side\n```js\nimport {createLoadableTransformer, getLoadableTrackerCallback} from 'react-imported-component/server';\nconst importedTracker = createLoadableTransformer(\n  loadableStream, // stream to observe \n  getLoadableTrackerCallback() // helper factory to create global tracker.\n);\n\n// pipe result of `renderToStream` throught it\nconst reactRenderStream = ReactDOM.renderToNodeStream(...).pipe(importedTracker);\n```\n3. Add `loadableTracker` at client side\n```js\n // index.js\n import './src/imported'; // the file generated by \"generate-imported-component\" (.2)\n import {injectLoadableTracker} from 'react-imported-component/boot';\n  \n injectLoadableTracker();\n  \n // load the rest after letting the browser kick off chunk loading\n // for example wrapping it in two Promises (1ms timeout or setImmediate)\n Promise.resolve().then(() =>\n   Promise.resolve().then(() => {\n     require('./main')\n   })\n );\n```\nThis \"hack\", will first introduce all possible `imports` to the `imported-component`, then gave it a \"tick\"\nto start loading required once, and only then execute the rest of the bundle.\nWhile the rest(99%) of the bundle would make CPU busy - chunks would be loaded over the network.\n> This is utilizing the differences between `parse`(unenviable) phase of script, and execute one.  \n\n# Cooking receipts\n\n## Partial hydration\nJust wrap \"partial hydrated\" component with _another_ `ImportedStream` so everything needed for it would be not automatically loaded with the main stream.\n\n## Hybrid render (CSR with prerendering)\nThis library could support hybrid rendering (aka pre-rendering) compatible in two cases:\n- pre-render supports `state hydration`, like `getState` in [react-snap](https://github.com/stereobooster/react-snap). See our [example](https://github.com/theKashey/react-imported-component/tree/master/examples/hybrid/react-snap).\n- for [rendertron](https://github.com/GoogleChrome/rendertron) or [https://prerender.io](https://prerender.io) follow `react-snap` example, just dump `state` using `setTimeout`.\n- You may use `react-prerendered-component` to maintain a component state until async chunk is not loaded. See example below.\n\n### Works better in pair (boiled-place-less code splitting)\nYou might not need to wait for all the chunks to be loaded before you can render you app - \njust use [react-prerendered-component](https://github.com/theKashey/react-prerendered-component).\n```js\nimport imported from 'react-imported-component';\nimport {PrerenderedComponent} from \"react-prerendered-component\";\n\nconst AsyncComponent = imported(() => import('./myComponent.js'));\n\n<PrerenderedComponent\n  // component will \"go live\" when chunk loading would be done\n  live={AsyncComponent.preload()}\n>\n  // until component is not \"live\" prerendered HTML code would be used\n  // that's why you need to `preload`\n  <AsyncComponent/>\n</PrerenderedComponent>\n```\nReact-prerendered-component is another way to work with code splitting, which makes everything far better.\n\n\n## CSS Support\n### CSS-in-JS Support\nFirst class. Literally CSS-in-JS library, like `styled-component` will do it by themselves, and there is nothing\nto be managed by this library\n\n### Static CSS Support\nThis library __does not__ support CSS as CSS, as long it's bundler independent. However, there is \na bundler independent way to support CSS:\n1. Configure you bundler, and server side rendering to emit the right `classNames` (just remove `style-loader` from webpack configuration)\n2. Use `used-styles` to inject used __css files__ to the resulting HTML.\n\nIn short (streamed example is NOT short)\n```js\n  const markup = ReactDOM.renderToString(<App />)\n  const usedStyles = getUsedStyles(markup, lookup);\n```\n\nIf you need `streamed` example with __reduced TTFB__ - \nplease refer to [used-styles](https://github.com/theKashey/used-styles) documentation, or our [parcel-bundler stream server example](https://github.com/theKashey/react-imported-component/tree/master/examples/SSR/parcel-react-ssr/stream-server).\n\n## Timeout to display \"spinners\"   \nThere is no build in timeouts to display Error or Loading states. You could control everything by yourself\n- use react-delay, p-delay, p-timeout, or `Suspense` :P.   \n\n## Component loader\nYou may use component api if you need it by any reason. \n```js\nimport {ComponentLoader} from 'react-imported-component';\n\nconst MyPage = () => (\n   <ComponentLoader\n       loadable={() => import('./Page.js')}\n       // all fields are optional, and matches the same field of importedComponent.\n       LoadingComponent={Loading}\n       ErrorComponent={Error}\n       onError\n       \n       exportPicker\n       render\n       async                 \n   />\n);\n```\n\n## SSR (Server side rendering)\nIt was usually a headache - async components and SSR, which is currently sync.\nReact-imported-component break this cycle, making ServerSide rendering sync, and providing\ncomprehensive ways to rehydrate rendered tree on client. \nIt will detect server-side environment and precache all used components.\n\n### Bundler independent SSR\nIt does not matter how do you bundle your application - it could be even browser. The secrect sause is a __cli__ command, to extract all your imports into imports map, and use it later to load chunks by request.\n- You might even dont have any separated chunk on the server side - it would still works.\n- You might even ship module/nomodule scripts, using, for example, [devolution](https://github.com/theKashey/devolution) - no additional configuration would be required.\n\n### Not using React.Lazy with React-Hot-Loader\nThere is design limitation with React.lazy support from RHL size, so they could not be reloaded without\nstate loss if `lazy` is created not in the user space. At it would be created inside imported.\n\nIf React-Hot-Loader is detected `lazy` switches to `imported async` mode, this behaves absolutely the same. \n\n## Other loaders\nAnother loaders exists, and the only difference is in API, and how they manage (or not manage) SSR.\n\n* (no SSR) React.Lazy \n* (webpack only) With [react-loadable](https://github.com/thejameskyle/react-loadable)\n* (not compatible with hooks) [react-async-component](https://github.com/ctrlplusb/react-async-component)   \n* (webpack only) [loadable-components](https://github.com/smooth-code/loadable-components)\n* (webpack only) [react-universal-component](https://github.com/faceyspacey/react-universal-component)  \n\n## Licence\nMIT\n","engines":{"node":">=8.5.0"},"gitHead":"2a37d45abdbb428c4ce78cf8322ff0c4ea6b78a8","license":"MIT","scripts":{"dev":"ts-react-toolbox dev","lint":"ts-react-toolbox lint","test":"ts-react-toolbox test","build":"ts-react-toolbox build","format":"ts-react-toolbox format","static":"ts-react-toolbox publish","analyze":"ts-react-toolbox analyze","release":"ts-react-toolbox release","test:ci":"ts-react-toolbox test --runInBand --coverage","prepublish":"npm run build"},"_npmUser":{"name":"kashey","email":"thekashey@gmail.com"},"homepage":"https://github.com/theKashey/react-hot-component-loader#readme","keywords":["react-hot-loader","loader","import","async","ssr","code splitting","hmr"],"repository":{"url":"git+https://github.com/theKashey/react-hot-component-loader.git","type":"git"},"size-limit":[{"path":"dist/es2015/index.js","limit":"3 KB"},{"path":"dist/es2015/boot.js","limit":"1.5 KB"}],"_npmVersion":"6.10.2","description":"I will import your component, and help to handle it","directories":{},"jsnext:main":"dist/es2015/index.js","maintainers":[{"name":"kashey","email":"thekashey@gmail.com"}],"sideEffects":false,"_nodeVersion":"10.15.3","dependencies":{"tslib":"^1.10.0","crc-32":"^1.2.0","prop-types":"^15.6.2","detect-node":"^2.0.4","scan-directory":"^1.0.0"},"_hasShrinkwrap":false,"readmeFilename":"README.md","devDependencies":{"sinon":"^5.0.10","size-limit":"^2.0.2","@babel/core":"^7.5.5","@types/node":"^12.7.2","@babel/runtime":"^7.3.1","ts-react-toolbox":"^0.2.2","@babel/preset-react":"^7.0.0","react-test-renderer":"^16.6.0","@size-limit/preset-small-lib":"^2.1.1","babel-plugin-dynamic-import-node":"^2.3.0"},"peerDependencies":{"react":"^16.3.0"},"_npmOperationalInternal":{"tmp":"tmp/react-imported-component_6.0.0-beta.2_1566714034450_0.7437665907688427","host":"s3://npm-registry-packages"},"_id":"react-imported-component@6.0.0-beta.2","version":"6.0.0-beta.2"}