Greg Bergé 4dffad7bd2 feat: welcome loadable
BREAKING CHANGE: API has completely changed, see documentation.
2018-10-29 13:04:07 +01:00
2018-10-29 13:04:07 +01:00
2017-10-10 21:53:47 +00:00
2018-10-29 13:04:07 +01:00
2018-10-29 13:04:07 +01:00
2018-10-29 13:04:07 +01:00
2017-06-23 15:34:04 +02:00
2018-10-29 13:04:07 +01:00
2018-02-02 15:24:21 +01:00
2018-10-29 13:04:07 +01:00
2018-10-29 13:04:07 +01:00
2018-08-16 09:16:19 +00:00
2018-10-29 13:04:07 +01:00
2017-06-23 15:34:04 +02:00
2018-10-29 13:04:07 +01:00
2018-10-29 13:04:07 +01:00
2018-10-29 13:04:07 +01:00

loadable-components

React code splitting made easy. Reduce your bundle size without stress ✂️.

License npm package npm downloads Build Status Code style Dependencies DevDependencies

npm install @loadable/component

Introduction

Code Splitting can be done easily using React.lazy. It is true if you don't need Server Side Rendering or complex features like full dynamic imports.

Loadable leverage the limit of Code Splitting and give you access to all features.

Code Splitting + Server Side Rendering is something very complex. Several libraries tried to solve this problem successfully or not. The goal of this library is to follow as much as possible the philosophy of React and give a developer-experience first solution to solve this complex problem. It takes the best from all libraries and provide an elegant solution to this problem.

Getting started

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>
  )
}

Suspense

@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>
  )
}

Suspense is not yet available for server-side rendering.

Custom loading

It is possible to add a custom loading component, by default it will render nothing.

Using a component

const Loading = () => <div>Loading...</div>

const Home = loadable(() => import('./Home'), {
  LoadingComponent: Loading,
})

Using render props

import React from 'react'

const Home = loadable(() => import('./Home'), {
  render: ({ Component, loading, ownProps }) => {
    if (loading) return <div>Loading...</div>
    return <Component {...ownProps} />
  },
})

Error handling

You can configure the component rendered when an error occurs during loading, by default it will display the error.

Using a component

const ErrorDisplay = ({ error }) => <div>Oups! {error.message}</div>

const Home = loadable(() => import('./Home'), {
  ErrorComponent: ErrorDisplay,
})

Using render props

import React from 'react'

const Home = loadable(() => import('./Home'), {
  render: ({ Component, error, ownProps }) => {
    if (error) return <div>Oups! {error.message}</div>
    return <Component {...ownProps} />
  },
})

Delay

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 Home = loadable(() => pMinDelay(import('./Home'), 200))

If you want to avoid these delay server-side:

import loadable from '@loadable/component'
import pMinDelay from 'p-min-delay'

const delay = promise => {
  if (typeof window === 'undefined') return promise
  return pMinDelay(promise, 200)
}

export const Home = loadable(() => delay(import('./Home')))

Timeout

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 Home = loadable(() => timeout(import('./Home'), 2000))

Prefetching

To enhance user experience, you can prefetch components, it loads component in background. This way you will avoid loading at first component display.

Each loadable component exposes a Prefetch component. It renders nothing but prefetch the component.

import loadable from '@loadable/component'

const OtherComponent = loadable(() => import('./OtherComponent'))

function MyComponent() {
  return (
    <div>
      {/* Nothing will be rendered, but the component will be loaded in background */}
      <OtherComponent.Prefetch />
    </div>
  )
}

A method prefetch is also exposed, you can call it to trigger prefetch on user action.

import loadable from '@loadable/component'

const OtherComponent = loadable(() => import('./OtherComponent'))

function MyComponent() {
  return (
    <div>
      <button onMouseOver={() => OtherComponent.prefetch()}>
        Prefetch on hover
      </button>
    </div>
  )
}

Only component based prefetching is compatible with Server Side Rendering.

Server side rendering

👉 See @loadable/server documentation.

MIT

Description
The recommended Code Splitting library for React ✂️
Readme MIT 20 MiB
Languages
JavaScript 70.8%
MDX 28.7%
Shell 0.5%