Need help with react-imported-component?
Click the “chat” button below for chat support from the developer who created it, or find similar developers for support.

About the developer

603 Stars 39 Forks MIT License 452 Commits 40 Opened issues


✂️📦Bundler-independent solution for SSR-friendly code-splitting

Services available


Need anything else?

Contributors list


Code splitting which always works*

imported components

SSR-friendly code splitting compatible with any platform.
Deliver a better experience within a single import.

npm downloads bundle size

* It's really will never let you down. All credits to your bundler.

👉 Usage | API | Setup | SSR | CCS Concurrent loading | Webpack/Parcel

| Library | Suspense | SSR | Hooks | Library | Non-modules | import(

) | babel-macro | webpack only | | ------------------- | :------: | :-: | :---: | :-----: | :---------: | :------------------: | :---------: | :----------: | | React.lazy | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | 😹 | no-ssr | | react-loadable | ✅ | ✅ | ❌ | ❌ | ✅ | ❌ | ❌ | 😿 | | @loadable/component | ✅ | ✅ | ❌ | ✅ | ❌ | ✅ | ❌ | 😿 | | imported-component | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ | ✅ | 😸 |

Read more about what this table displays

Key features:

  • 1️⃣ Single source of truth - your bundler drives everything
  • 📖 library level code splitting
  • 🧙️ Hybrid and Prerendering compatible
  • 💡 TypeScript bindings
  • ⚛️ React.Lazy underneath (if hot module updates are disabled)
  • 🌟 Async on client, sync on server. Supports Suspense (even on server side)
  • 📦 could work with any bundler - webpack, rollup, parcel or puppeteer - it does not matter
  • 🤹‍♂️ working as well with any
    you may provide

Other features:

  • 🔥 Hot-Module-Replacement/React-Hot-Loader friendly
  • ⛓️ support forwardRef
  • ⚛️ React 16/Async/Hooks ready
  • 🛠 HOC, Component, Hooks API
  • 🐳 stream rendering support
  • 👥 partial hydration out of the box
  • 📦 and yes - this is the only parcel-bundler compatible SSR-friendly React code splitting library, as well as a perfect solution for Create React App

👍 Better than React.Lazy:

  • It IS Lazy, just with some stuff around*
  • SSR, Prerendering and Preloading support
  • With or without Suspense, and easier Error cases support

👍 Better than others:

  • Not bound to webpack
  • Easy way to use per-browser(modern/legacy) bundles - you down have to mess with actual browser support
  • Strong typing
  • Working with any imports, even native, external or derived ones.

👌 Client-side module resolution

  • Loads chunks only after the
    main one
    , as long as loader code is bundled inside the main chunk, so it should be loaded first.
  • Not an issue with the
    progressive hydration
    , and might provide a better UX via feature detection.
  • Provides 👨‍🔬 technological workaround - see here

📦 Optional bundler integration for the best experience

  • prefetching backed by webpack
  • parcel-manifest.json

👯‍♀️Works better in pair


Server side

Just a proper setup and a bit of magic

Client side


provides 2 common ways to define a component, which are more different inside than outside
  • using
import importedComponent from 'react-imported-component';
const Component = importedComponent( () => import('./Component'));

const Component = importedComponent( () => import('./Component'), { LoadingComponent: Spinner, // what to display during the loading ErrorComponent: FatalError // what to display in case of error });

Component.preload(); // force preload

// render it <component...></component...>

  • using
    API. It's almost the same
    outside, and exactly the same inside.
import { lazy, LazyBoundary } from 'react-imported-component';
const Component = lazy(() => import('./Component'));

const ClientSideOnly = () => ( );

// or let's make it SSR friendly const ServerSideFriendly = () => ( {' '} // LazyBoundary is Suspense* on the client, and "nothing" on the server );

is a
on Client Side, and
on Server Side. Don't forget - "dynamic" imports are sync on a server.

Example: React.lazy vs Imported-component


However, you may not load only components - you may load anything

import {useImported} from 'react-imported-component'

const MyCalendarComponent = () => { const { imported: moment, loading } = useImported(() => import("moment"));

return loading ? "..." : today is {moment(} }

// or we could make it a bit more interesting...

const MyCalendarComponent = () => { const { imported: format = x => "---", // default value is used while importing library } = useImported( () => import("moment"), moment => x => moment(x).format // masking everything behind );

return today is {format( }

What you could load using

? Everything -
itself is using it to import components.

is an excellent example for loading translations, which are usually a simple json, in a trackable way.

💡 did you know that there is another hook based solution to load "something might might need"? The use-sidecar pattern.

🤔 Keep in mind - everything here is using

, and you can build whatever you need using just it.


A slim helper to help handle

, you might require using
in a component way
import { importedModule, ImportedModule } from 'react-imported-component';

const Moment = importedModule(() => import('moment'));

{(momentjs /* default imports are auto-imported*/) => momentjs(date).fromNow()} ;

Yes, this example was taken from loadable.lib

Can I also use a ref, populated when the library is loaded? No, you cant. Use

for any special case like this.

Plus, there is a Component helper:

 import('moment').then(({momentDefault})=> momentDefault(date).fromNow()}
 fallback="long time ago"
 {(fromNow) => fromNow()}

ImportedModule will throw a promise to the nearest Suspense boundary if no


Babel macro

If you could not use babel plugin, but do have

(like CRA) - consider using macro API:
import { imported, lazy, useImported } from 'react-imported-component/macro';
// notice - there is no default import here

Indirect usage

Just importing

would enable babel transformation for the current file. If you have
definition in one file, and use it from another - just
import "react-imported-component/macro"
in that another file. See #142


Don't forget - there are TS typings provided.

Code splitting components

import {*} from 'react-imported-component';

  • importedComponent(importFunction, [options]): ComponentLoader
    - main API, default export, HOC to create imported component.
    • importFunction
      - function which resolves with Component to be imported.
    • options
      - optional settings
    • 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. See working with Suspense
    • options.LoadingComponent
      - component to be shown in Loading state
    • options.ErrorComponent
      - component to be shown in Error state. Will re-throw error if ErrorComponent is not set. Use ErrorBoundary to catch it.
    • options.onError
      - function to consume the error, if one will thrown. Will rethrow a real error if not set.
    • options.exportPicker
      - function to pick
      not default
      export from a
    • options.render(Component, state, props)
      - function to render the result. Could be used to tune the rendering.
    • [static]
      - static method to preload components.
  • lazy(importFunction)
    - helper to mimic React.lazy behavior
  • useImported(importFunction, [exportPicker], [options])
    - code splitting hook
    • importFunction
      - a function which resolves to
      import(T | {default:T})
    • [exportPicker]
      - function to pick "T" from the import
    • [options]
      - options to the hook
    • [options.import]
      - controls import. Hooks would be executed only if this is not false
    • [options.track]
      - ability to disable server-side usage tracking.

returns complex object(ImportedShape):
  • imported
    - the imported resource
  • error
    - error (if present)
  • loading
    - is it loading right now?
  • loadable
    - the underlying
  • retry
    - retry action (in case of error)


  • use
    to perform conditional import -
    would not be used if this option set to `false.
  • use
    to perform SSR only import - to usage would be tracked if this option set to `false.
  •  - a controller for Suspense Hydration. Compulsory for async/lazy usecases

There is also API method, unique for imported-component, which could be useful on the client side

  • addPreloader(fn):fn
    - adds a function, result of which would be awaited when any component is loaded. Returns cancel method.

Server side API

import {*} from 'react-imported-component/server';

  • whenComponentsReady():Promise
    - will be resolved, when all components are loaded. Usually on the next "Promise" tick.
  • drainHydrateMarks([stream])
    - returns the currently used marks, and clears the list.
  • printDrainHydrateMarks([stream])
    - print our the

Stream API

  • createLoadableStream
    - creates a steam
  • ImportedStream
    - wraps another component with import usage tracker.
  • createLoadableTransformer
    - creates nodejs StreamTransformer
  • getLoadableTrackerCallback
    - helper factory for the stream transformer

Client side API

import {*} from 'react-imported-component/boot';

  • whenComponentsReady():Promise
    , will be resolved, when all (loading right now) marks are loaded.
  • rehydrateMarks([marks]):Promise
    , loads marked async chunks.
  • injectLoadableTracker
    - helper factory for the stream transformer



All imports inside library are converted into

object, and it's often accessible from outside via
(not documented),
(not documented). Even if it's documented from TS point of view - let's keep all fields in a secret, except one:
  • resolution
    - promise reflecting resolution of this loadable object


In short

  1. Add
  2. Run
    yarn imported-components src src/imported.js
    to extract all your imports into a
    run time chunk
    (aka async-requires).
  3. Replace
    with our
    , and
    with our
    . Literraly monkey-patch React to do so
  4. Add
    to the server code.
  5. Add
    to the client code
  6. Done. Just read the rest of readme for details.

There are examples for webpack, parcel, and react-snap. Just follow them.

1. Configure babel plugin

On the server:

  "plugins": ["react-imported-component/babel", "babel-plugin-dynamic-import-node" /* might be optional for babel 7*/]

On the client:

  "plugins": ["react-imported-component/babel"]

Imported-Component will hook into dynamic imports, providing extra information about files you want to load.

2. Add one more command into package.json

CLI command

imported-components [sources ROOT] [targetFile.js]
(use .ts for TypeScript)
 "generate-imported-component": "imported-components src src/imported.js"

When you will execute this command - all

among your codebase would be found and extracted to a file provided. This will gave ability to orchestrate code-splitting later.

If you need to search inside more that one top-level directory - just define more command, saving information into more than one target file.

The current implementation will discover and use all

, even // commented ones

💡 Feel free to .gitignore these autogenerated files

3. Start using

Without you using API provided nothing would work.

4. Add server side tracking

There are two ways to do it - in a single threaded way, and async

Single threaded

import { printDrainHydrateMarks, drainHydrateMarks } from 'react-imported-component';
// this action will "drain" all currently used(by any reason) marks
// AND print a script tag
const html = renderToString() + printDrainHydrateMarks();

// OR return list of usedmarks, and yet again CLEAR the marks list. const html = renderToString() + '';

renderToStream or async render

import {createLoadableStream} from 'react-imported-component/server';

let importedStream = createLoadableStream(); // ImportedStream is a async rendering "provider" const stream = renderToStream( );

// you'd then pipe the stream into the response object until it's done stream.pipe(res, { end: false });

// and finalize the response with closing HTML stream.on('end', () => // print marks used in the file res.end(`${printDrainHydrateMarks(importedStream)}

We use cookies. If you continue to browse the site, you agree to the use of cookies. For more information on our use of cookies please see our Privacy Policy.