React code splitting made easy. Reduce your bundle size without stress ✂️✨.
npm install @loadable/component
Code splitting is supported out of the box by React using React.lazy
. So what is the goal of this library?
@loadable/component
pushes the limit of Code splitting, it offers several features:
- 📚 Library splitting
- ⚡️ Prefetching
- 💫 Server Side Rendering
- 🎛 Full dynamic import
import(`./${value}`)
Library | Suspense | SSR | Library splitting | import(`./${value}`) |
---|---|---|---|---|
React.lazy |
✅ | ❌ | ❌ | ❌ |
react-loadable |
❌ | 🔶 | ❌ | ❌ |
@loadable/component |
✅ | ✅ | ✅ | ✅ |
loadable
lets you render a dynamic import as a regular component.
import loadable from '@loadable/component'
const OtherComponent = loadable(() => import('./OtherComponent'))
function MyComponent() {
return (
<div>
<OtherComponent />
</div>
)
}
loadable.lib
lets you defer the loading of a library. It takes a render props called when the library is loaded.
import loadable from '@loadable/component'
const Moment = loadable.lib(() => import('moment'))
function FromNow({ date }) {
return (
<div>
<Moment fallback={date.toLocaleDateString()}>
{({ default: moment }) => moment(date).fromNow()}
</Moment>
</div>
)
}
You can also use a ref
, populated when the library is loaded.
import loadable from '@loadable/component'
const Moment = loadable.lib(() => import('moment'))
class MyComponent {
moment = React.createRef()
handleClick = () => {
if (this.moment.current) {
return alert(this.moment.current.default.format('HH:mm'))
}
}
render() {
return (
<div>
<button onClick={this.handleClick}>What time is it?</button>
<Moment ref={this.moment} />
</div>
)
}
}
You can also pass a function to
ref
, called when the library is loaded.
Webpack accepts full dynamic imports, you can use them to create a reusable Loadable Component.
import loadable from '@loadable/component'
const AsyncPage = loadable(props => import(`./${props.page}`))
function MyComponent() {
return (
<div>
<AsyncPage page="Home" />
<AsyncPage page="Contact" />
</div>
)
}
@loadable/component
exposes a lazy
method that acts similarly as React.lazy
one.
import { lazy } from '@loadable/component'
const OtherComponent = lazy(() => import('./OtherComponent'))
function MyComponent() {
return (
<div>
<Suspense fallback={<div>Loading...</div>}>
<OtherComponent />
</Suspense>
</div>
)
}
Use
lazy.lib
for libraries.
⚠️ Suspense is not yet available for server-side rendering.
You can specify a fallback
in loadable
options.
const OtherComponent = loadable(() => import('./OtherComponent'), {
fallback: <div>Loading...</div>,
})
function MyComponent() {
return (
<div>
<OtherComponent />
</div>
)
}
You can also specify a fallback
in props:
const OtherComponent = loadable(() => import('./OtherComponent'))
function MyComponent() {
return (
<div>
<OtherComponent fallback={<div>Loa
8000
ding...</div>} />
</div>
)
}
If the other module fails to load (for example, due to network failure), it will trigger an error. You can handle these errors to show a nice user experience and manage recovery with Error Boundaries. Once you’ve created your Error Boundary, you can use it anywhere above your lazy components to display an error state when there’s a network error.
import MyErrorBoundary from '/MyErrorBoundary'
const OtherComponent = loadable(() => import('./OtherComponent'))
const AnotherComponent = loadable(() => import('./AnotherComponent'))
const MyComponent = () => (
<div>
<MyErrorBoundary>
<section>
<OtherComponent />
<AnotherComponent />
</section>
</MyErrorBoundary>
</div>
)
To avoid flashing a loader if the loading is very fast, you could implement a minimum delay. There is no built-in API in @loadable/component
but you could do it using p-min-delay
.
import loadable from '@loadable/component'
import pMinDelay from 'p-min-delay'
// Wait a minimum of 200ms before loading home.
export const OtherComponent = loadable(() =>
pMinDelay(import('./OtherComponent'), 200),
)
Infinite loading is not good for user experience, to avoid it implementing a timeout is a good workaround. You can do it using a third party module like promise-timeout
:
import loadable from '@loadable/component'
import { timeout } from 'promise-timeout'
// Wait a maximum of 2s before sending an error.
export const OtherComponent = loadable(() =>
timeout(import('./OtherComponent'), 2000),
)
Loadable Components is fully compatible with webpack hints webpackPrefetch
and webpackPreload
.
Most of the time, you want to "prefetch" a component, it means it will be loaded when the browser is idle. You can do it by adding /* webpackPrefetch: true */
inside your import statement.
import loadable from '@loadable/component'
const OtherComponent = loadable(() =>
import(/* webpackPrefetch: true */ './OtherComponent'),
)
You can extract prefetched resources server-side to add
<link rel="prefetch">
in your head.
👉 See @loadable/server
documentation.
Create a loadable component.
Arguments | Description |
---|---|
loadFn |
The function call to load the component. |
options |
Optional options. |
options.fallback |
Fallback displayed during the loading. |
import loadable from '@loadable/component'
const OtherComponent = loadable(() => import('./OtherComponent'))
Create a loadable component "Suspense" ready.
Arguments | Description |
---|---|
loadFn |
The function call to load the component. |
import { lazy } from '@loadable/component'
const OtherComponent = lazy(() => import('./OtherComponent'))
A component created using loadable
or lazy
.
Props | Description |
---|---|
fallback |
Fallback displayed during the loading. |
... |
Props are forwarded as first argument of loadFn |
Create a loadable library.
Arguments | Description |
---|---|
loadFn |
The function call to load the component. |
options |
Optional options. |
options.fallback |
Fallback displayed during the loading. |
import loadable from '@loadable/component'
const Moment = loadable.lib(() => import('moment'))
Create a loadable library "Suspense" ready.
Arguments | Description |
---|---|
loadFn |
The function call to load the component. |
import { lazy } from '@loadable/component'
const Moment = lazy.lib(() => import('moment'))
A component created using loadable.lib
or lazy.lib
.
Props | Description |
---|---|
children |
Function called when the library is loaded. |
ref |
Accepts a ref, populated when the library is loaded. |
fallback |
Fallback displayed during the loading. |
... |
Props are forwarded as first argument of loadFn |