대부분 React 앱들은 Webpack, Rollup과 같은 툴을 사용해 번들링(Bundling)한다. 그 이유는 HTML 웹 페이지에 JavaScript를 쉽게 추가할 수 있기 때문이다.
모던 웹으로 발전하면서 점점 DOM을 다루는 정도가 정교해지며 JavaScript 코드 자체가 방대해지고 무거워졌다. 그래서 코드 분할이 등장하게 되었다.
지금 당장 필요한 코드가 아니라면 따로 분리를 시키고, 나중에 필요할 때 불러와서 사용할 수 있다. 대규모 프로젝트의 앱인 경우에도 페이지의 로딩 속도를 개선할 수 있게 된다.
사용하지 않는 모든 컴포넌트까지 한 번에 불러오기 때문에 첫 화면이 렌더링 될 때까지의 시간이 오래 걸린다. 그래서 사용하지 않는 컴포넌트는 나중에 불러오기 위해 코드 분할 개념을 도입했다.
form.addEventListener("submit", e => {
e.preventDefault();
/* 동적 불러오기는 이런 식으로 코드의 중간에 불러올 수 있게 된다. */
import('library.moduleA')
.then(module => module.default)
.then(someFunction())
.catch(handleError());
});
const someFunction = () => {
/* moduleA를 여기서 사용. */
}
dynamic import는 then 함수를 사용해 필요한 코드만 가져온다.
React는 React.lazy를 통해 컴포넌트를 동적으로 import를 할 수 있기 때문에 초기 렌더링 지연시간을 어느 정도 줄일 수 있게 된다.
import Component from './Component';
/* React.lazy로 dynamic import를 감싸기. */
const Component = React.lazy(() => import('./Component'));
아직 렌더링이 준비되지 않은 컴포넌트가 있을 때 로딩 화면을 보여주고, 로딩이 완료되면 렌더링이 준비된 컴포넌트를 보여주는 기능이다.
/* suspense 기능을 사용하기 위해서는 import 해와야 한다. */
import { Suspense } from 'react';
const OtherComponent = React.lazy(() => import('./OtherComponent'));
const AnotherComponent = React.lazy(() => import('./AnotherComponent'));
function MyComponent() {
return (
<div>
{/* 이런 식으로 React.lazy로 감싼 컴포넌트를 Suspense 컴포넌트의 하위에 렌더링한다. */}
<Suspense fallback={<div>Loading...</div>}>
{/* Suspense 컴포넌트 하위에 여러 개의 lazy 컴포넌트를 렌더링시킬 수 있다. */}
<OtherComponent />
<AnotherComponent />
</Suspense>
</div>
);
}
fallback prop은 컴포넌트가 로드될 때까지 기다리는 동안 로딩 화면으로 보여줄 React 엘리먼트를 받아들인다.
앱에 코드 분할을 도입할 곳을 결정하는 것은 사실 까다롭기 때문에, 웹 페이지를 불러오고 진입하는 단계인 Route에 이 두 기능을 적용시키는 것이 좋다.