📦 React-Imported-Component v6
Tags: react, webdev, codesplitting
Published: 2019-10-04 01:23:36

---
title: 📦 React-Imported-Component v6
published: true
description: moving lazy loading the to new horizons
tags: React, web dev, code splitting
cover_image: https://thepracticaldev.s3.amazonaws.com/i/6mug2aliiy70m5e0ggw5.jpg
---
> Long story short - nobody cares about version 1 and 2 - by that time the library, I am going to talk about, even had a different name. Version 3 never existed and the difference between 4 and 5 was a `forwardRef`, or React 16 support, which is a good reason for a breaking change. So, in  short, v6 is actually 3rd iteration on the API.

Bump to a version 6 was also driven by new React features. This time by hooks, making React-imported-component the first code-splitting library with exposed __hook API__, as well as the first __Create-React-App compatible__ one, thanks to the babel __macros__ support.

### Stop stop stop, why not just Lazy?
__Server Side Rendering__, tracking, and advanced API. Here is the comparison table:

![Comparison table](https://thepracticaldev.s3.amazonaws.com/i/uh77nrecklgjpkt7hpe9.png)

Ready? Jump in!

{% github theKashey/react-imported-component %}

## useImported hook
Lazy-loading is not only about `React.lazy` and `Components` - behind any variant there is nothing more but a dynamic `import`, which able to load absolute everything. And all you need - is a proper "React integration" to manage loading states.

```js
// a STATIC table with imports
const languages = {
  'en': () => import('./i18n/en'), // it's probably a json...
  'de': () => import('./i18n/de'),
}
// just a helper function
const pickLanguage = (lng) => languages[lng];
// your component
const MyI18nProvider = ({lng, children}) => {
  // let's pick and provide correct import function for our language
  const {
   imported: messages = {} // defaulting to empty object
  } = useImported(pickLanguage(lng));

  // set messages to the Provider
  return <I18nProvider value={messages}>{children}</I18nProvider>
}
```
That's all. The only problem is with default `{}`, unique on every render, so better extract them to a separate variable outside of this component. However, this is not something you should worry about. 

`useImported` could load whatever you want, and any other API exposed by `react-imported-component` is built on it.

## importedModule and ImportedModule
`useImported` is not always super handfull, sometimes something more _declarative_ could be preferred. 
So there is a helper to import anything you want via react __render props__ interface. For the majority, this pattern is better known as [loadable.lib](https://www.smooth-code.com/open-source/loadable-components/docs/library-splitting/) (however it was first introduced for imported)

```js
import {importedModule, ImportedModule} from 'react-imported-component';

// you can use it to codesplit and  use `momentjs`, no offence :)
const Moment = importedModule(() => import('moment'));

<Moment fallback="long time ago">
  {(momentjs /* default imports are auto-imported*/) => momentjs(date).fromNow()}
</Moment>

// or, again, translations

<ImportedModule
 import={() => import('./i18n/en')}
 // fallback="..." // will throw to the Suspense boundary without fallback provided
>
 {(messages) => <I18nProvider value={messages}>{children}</I18nProvider> }
</ImportedModule>
```

## imported and lazy
There is also two "common" APIs - `imported` and `lazy`.
Where `lazy` - quacks like a `React.lazy`, and __is__ lazy in production, while `imported` is, well, old good imported with API compatible with the _first generation_ of code splitting libraries.
```js
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... />
```

# Extra stuff

## Create React App support
There are 3 things you should know about CRA:
- it's hard to change the configuration of your project, and you are encouraged not to do it
- it supports SSR or Prerendering
- that's makes better code splitting a bit complicated

However, while other SSR friendly code-splitting solutions require __babel__ and __webpack__ plugins to work - `react-imported-component` don't need anything from webpack, it's bundler independent, and provides a __babel macro__, the only thing which works out of the box with CRA.

Just use `react-imported-component/macro`, and call it a day
```js
import {imported} from "react-imported-component/macro";
imported(()=>import('./aGoodDay'));
```

## Bundler independency
This means again 3 different things:
- it's parcel bundler compatible, or rollup, or systemjs. It does not matter what bundler you use - it would work.
- it's [react-snap](https://github.com/stereobooster/react-snap) - compatible. "Usage tracking" never stops, and after rendering your page in a headless browser you might ask it - "which chunks you need to render the same again", and be given a list. As well it works with unmanaged "real" `imports`. It basically does not matter.
- it __was__ not so efficient as code splitting solutions with more deeper integrations, so they could flush used chunks during SSR. And, as I said - it was.

### Loading orchestration
The first way to make script rehydration is to make the loading process more efficient. `imported-component` provides a separate entry point - `/boot` to kick off initialization process before the main script evaluation, thus load deferred scripts a bit early. A great solution for CRA or Parcel, where you might not know real names of chunks files(without extra plugins installed) to inline into HTML.

```js
import "../async-requires";
import {injectLoadableTracker} from "react-imported-component/boot";
// ^ just 1kb

// injects runtime
injectLoadableTracker('importedMarks');


// give browser a tick to kick off script loading
Promise.resolve().then(() =>
  Promise.resolve().then(() => { 
    // the rest of your application
    // imported with a little "pause"
    require('./main')
  })
);
```

This works quite simple and interesting - you js got parsed, got evaluated, but __not fully executed__. Then `imported` will trigger importing loading the required chunks, just calling `imports` it shall call. Then your application will continue the execution.

Let me provide two lighthouse snapshots(4x slowdown, 3Mb JS bundle) to explain the idea:
- requiring `main` in a promise, as in the example above
![full script evaluation](https://thepracticaldev.s3.amazonaws.com/i/nogp0v9yy47guo81qvgm.png)
- not requiring `main` in a promise, as in the example above (just moved it to the `catch`, all code still in the bundle)
![boot bundle](https://thepracticaldev.s3.amazonaws.com/i/a6nnfoqoqc6akm9qa2dj.png)


Or you will more believe in Profiler flame graphs?

![first chunk](https://thepracticaldev.s3.amazonaws.com/i/td2dad0ja1p4574yzbr0.png)
Notice small "time box" on the left, and __microtasks__ given to browser, to kick off network stuff on the right.

![full time](https://thepracticaldev.s3.amazonaws.com/i/3c708omasaer1gpu3d41.png)

And notice how small was that "time box".

This makes all those things, like script preloading and prefetching, not as important - it would be not so bad even without them. So you might have good SSR with CRA out of the box.


### Deep Webpack integration
However, the best results require a more fine-grained approach. And another change for v6 - a separate package for webpack integration - will be able to help. Named quite obviously:

{% github theKashey/webpack-imported %}

A webpack plugin to gather the data, and clientside API, including React binding, to handle everything out of the box.

```js
import importedData from 'build/imported.json';

<WebpackImport
   stats={importedData}
   chunks={getMarkedChunks(marks)}
   publicPath={importedData.config.publicPath}
   crossOrigin={CDN_ANONYMOUS}
/>
```

### CSS
And CSS is also handled in the best possible way - with __critical style extraction__ working out of the box for a plain CSS files.

{% github theKashey/used-styles %}


### Streaming

All used libraries have Streamig-friendly API, and able to provide the best TTFB you are looking for.

## Why Why Why

If you are looking for answers Why To Code Split, What to Code Split and When to Code Split, as well as how to optimize JS or CSS delivery.

{% link https://dev.to/thekashey/code-splitting-what-when-and-why-59op %}

# Conclusion

- hooks API
- loading modules
- loading components​
- with server-side tracking
- babel macro support
- not bound to webpack, however best of class support for a deeper browser integration
- build just for you!

👉 https://github.com/theKashey/react-imported-component