Next.js는 ES2020의 Dynamic import를 지원한다.
이를 통해 동적으로 자바스크립트 모듈을 가져와 사용할 수 있다.
또한 Dynamic import SSR로 동작한다.
다음 예제에서는 fuse.js를 사용하여 퍼지 검색을 구현하고
사용자가 검색 입력을 입력한 후에만 브라우저에게 모듈을 동적으로 로드하여 첫 렌더링의 성능을 개선할 수 있다.
import { useState } from 'react'
const names = ['Tim', 'Joe', 'Bel', 'Max', '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>
)
}
Dynamic import는 코드를 관리가능한 단위(chunks)로 분할하는 또 다른 방법으로 생각할 수 있다.
React Components는 Dynamic imports를 사용하여 import할 수도 있지만 이 경우 next/dynamic
과 함께 사용하여 다른 React components처럼 동작하는지 확인한다.
다음 예제에서 ../components/hello
모듈은 페이지에서 동적으로 로드된다.
import dynamic from 'next/dynamic'
const DynamicComponent = dynamic(() => import('../components/hello'))
function Home() {
return (
<div>
<Header />
<DynamicComponent />
<p>HOME PAGE is here!</p>
</div>
)
}
export default Home
위 예제에서 DynamicComponents는 ../components/hello
에서 반환되는 default Component가 된다.
일반 React의 Component처럼 동작하며, props 또한 전달 가능하다.
다만 import(path/to/component)
에 템플릿 문자열이나 변수를 사용할 수 없다.
또한 import()는 webpack의 번들/모듈 ID를 dynamic()호출과 일치시켜 렌더링 이전에 로드할 수 있도록 dynamic()호출 내부에 있어야 한다.
dynamic()은 React.lazy와 유사하게 사전 로드가 작동하도록 모듈의 최상위 수준에 표시되어야 하므로 React 렌더링 내부에서 사용할 수 없다.
Dynamic component가 default export가 아니라면, 작명하여 export로 사용할 수 있다. 작명된 component를 Dynamic import로 가져오려면 import()에 의해 반환된 Promise에서 반환할 수 있다.
//components/hello.js
export function Hello() {
return <p>Hello!</p>
}
import dynamic from 'next/dynamic'
const DynamicComponent = dynamic(() =>
import('../components/hello').then((mod) => mod.Hello)
)
function Home() {
return (
<div>
<Header />
<DynamicComponent />
<p>HOME PAGE is here!</p>
</div>
)
}
export default Home
Dynamic import로 설정된 Component가 로드되는 동안, Loading state를 추가할 수 있다.
import dynamic from 'next/dynamic'
const DynamicComponentWithCustomLoading = dynamic(
() => import('../components/hello'),
{ loading: () => <p>...</p> }
)
function Home() {
return (
<div>
<Header />
<DynamicComponentWithCustomLoading />
<p>HOME PAGE is here!</p>
</div>
)
}
export default Home
서버사이드에서 모듈을 항상 포함하는것을 원치 않는다면,
예를 들어 브라우저에서만 동작하는 라이브러리를 포함한 모듈을 포함하는 것을 원치 않는다면 아래와 같이 사용할 수도 있다.
import dynamic from 'next/dynamic'
const DynamicComponentWithNoSSR = dynamic(
() => import('../components/hello3'),
{ ssr: false }
)
function Home() {
return (
<div>
<Header />
<DynamicComponentWithNoSSR />
<p>HOME PAGE is here!</p>
</div>
)
}
export default Home
Option suspense를 사용하면 React.lazy 및 React18의 <Suspense>
와 유사한 Component를 lazy-load할 수 있다.
import dynamic from 'next/dynamic'
const DynamicLazyComponent = dynamic(() => import('../components/hello4'), {
suspense: true,
})
function Home() {
return (
<div>
<Suspense fallback={`loading`}>
<DynamicLazyComponent />
</Suspense>
</div>
)
}