Dynamic import()

We can use import() to load a component in a lazy manner:

- import SomeComponent from 'some-component'
+ const { SomeComponent } = await import('some-component')

Vite automatically code-splits at import(): the code of some-component isn't included in the initial JavaScript bundle and is loaded only if/when import('some-component') is executed.

Common use cases:

  • Performance: we can use import() to defer loading a heavy component (e.g. an interactive map), so that the user can already interact with our page before even the browser starts loading that heavy component.
  • Client-side only components: we can use import() to avoid loading/rendering a component on the server-side. (Some component libraries cannot be server-side rendered, see Guides > Client-only Components.)

UI framework support for lazy-loading components using import():

React Example

// pages/location/pick.page.jsx

import React from 'react'

export function Page() {
  // Users can see and interact with the button "Please pick a location"
  // before the browser starts loading the code for <Map>.
  return <>
    <button>Please pick a location</button>
    <Map />
  </>
}

// <Map> is:
//  - Lazy-loaded
//  - Loaded and rendered only in the browser
function Map() {
  const [Component, setComponent] = React.useState(() => Loading)

  // useEffect() callbacks are only run in the browser, consequently the map component
  // is loaded and rendererd only in the browser.
  React.useEffect(() => {
    // @ts-ignore React.lazy's type is wrong
    setComponent(() => React.lazy(() => import('some-heavy-map-component')))
  }, [])

  return (
    <React.Suspense fallback={<Loading />}>
      <Component />
    </React.Suspense>
  )
}

function Loading() {
  return <div>Loading map...</div>
}

We can extract the logic into a generic <ClientOnly> component:

import React from 'react'

function Map() {
  return (
    <ClientOnly
      load={() => import('some-heavy-map-component')}
      fallback={<Loading />}
    />
  )
}

function ClientOnly({ load, fallback }) {
  const [Component, setComponent] = React.useState(() => fallback)

  React.useEffect(() => {
    setComponent(() => React.lazy(load))
  }, [])

  return (
    <React.Suspense fallback={fallback}>
      <Component />
    </React.Suspense>
  )
}

See also:

Vue Example

See #278 - comment. Contribution welcome to create a full example.