Skip to content
On this page

Dynamic Import

Examples

Next.js supports lazy loading external libraries with import() and React components with next/dynamic. Deferred loading helps improve the initial loading performance by decreasing the amount of JavaScript necessary to render the page. Components or libaries are only imported and included in the JavaScript bundle when they're used.

next/dynamic is an extension of React.lazy. When used in combination with Suspense, components can delay hydration until the Suspense boundary is resolved.

Example

By using next/dynamic, the header component will not be included in page's the initial JavaScript bundle. The page will render the Suspense fallback first, followed by the Header component when the Suspense boundary is resolved.

jsx
import dynamic from 'next/dynamic'
import { Suspense } from 'react'

const DynamicHeader = dynamic(() => import('../components/header'), {
  suspense: true,
})

export default function Home() {
  return (
    <Suspense fallback={`Loading...`}>
      <DynamicHeader />
    </Suspense>
  )
}

Note: In import('path/to/component'), the path must be explicitly written. It can't be a template string nor a variable. Furthermore the import() has to be inside the dynamic() call for Next.js to be able to match webpack bundles / module ids to the specific dynamic() call and preload them before rendering. dynamic() can't be used inside of React rendering as it needs to be marked in the top level of the module for preloading to work, similar to React.lazy.

If you are not using React 18, you can use the loading attribute in place of the Suspense fallback.

jsx
const DynamicHeader = dynamic(() => import('../components/header'), {
  loading: () => <header />,
})

With named exports

To dynamically import a named export, you can return it from the Promise returned by import():

jsx
// components/hello.js
export function Hello() {
  return <p>Hello!</p>
}

// pages/index.js
import dynamic from 'next/dynamic'

const DynamicComponent = dynamic(() =>
  import('../components/hello').then((mod) => mod.Hello)
)

With no SSR

To dynamically load a component on the client side, you can use the ssr option to disable server-rendering. This is useful if an external dependency or component relies on browser APIs like window.

jsx
import dynamic from 'next/dynamic'

const DynamicHeader = dynamic(() => import('../components/header'), {
  ssr: false,
})

With external libraries

This example uses the external library fuse.js for fuzzy search. The module is only loaded in the browser after the user types in the search input.

jsx
import { useState } from 'react'

const names = ['Tim', 'Joe', 'Bel', 'Lee']

export default function Page() {
  const [results, setResults] = useState()

  return (
    <div>
      <input
        type="text"
        placeholder="Search"
        onChange={async (e) => {
          const { value } = e.currentTarget
          // Dynamically load fuse.js
          const Fuse = (await import('fuse.js')).default
          const fuse = new Fuse(names)

          setResults(fuse.search(value))
        }}
      />
      <pre>Results: {JSON.stringify(results, null, 2)}</pre>
    </div>
  )
}