앞 전에 suspense를 정리하였다. suspense가 기반되어야 쓸 수 있는 코드에 대해서 정리해보고자 한다.
code-splitting
영어 단어 그대로 코드를 나눈다는 것이다. 왜 이것이 필요할까? 앱이 커짐에 따라 번들도 커지게 된다. 특히 큰 third-party라이브러리를 포함하는 경우에 번들에 포함된 코드를 주의깊게 확인해야 한다. 실수로 커진 앱으로 인해 로드시간이 오래 걸리는 문제를 방지한다.
큰 번들로 묶이지 않으려면 번들을 code splitting 하는것이 좋다. code splitting 기능은 런타임시 동적으로 로드할 수 있는 여러 번들을 만들 수 있는 Webpack 및 Browserify와 같은 번들러에서 지원되는 기능이다.
code splitting을 하면 사용자가 현재 필요로하는 것들만 lazy-load할 수 있다. 이 말이 무슨 말이냐면 우리가 맨 처음 들어가는 페이지의 리소스만 다운받고, 페이지 이동시 그 페이지 리소스만 다운받게 한다는 말이다. 앱의 성능을 크게 향상시킬 수 있습니다. 앱의 전체 코드 양을 줄이지는 않지만, 사용자가 필요로하지 않은 코드를 로드하는 것을 피하게 된다.
Dynamic import
Dynamic Import 는 일반적인 정적인 Module Import 를 필요한 시점 에 로드 할 수 있도록 도와준다. 이를 이용하면 거대한 하나의 js를 여러개로 쪼갤 수 있고, 화면이 위치할때마다 import 할 수 있다.
import(...)표현식은 모듈을 읽고 내보내는 모든 것을 포함하는 객체를 담는 Promise를 반환한다. 호출은 어디에서든 가능하다.
import('./sum').then(sum => {
console.log(sum(1 + 2));
});
React.lazy
import React, { Suspense, lazy } from 'react';
import { BrowserRouter as Router, Route, Switch } from 'react-router-dom';
const Home = lazy(() => import('./routes/Home'));
const About = lazy(() => import('./routes/About'));
const App = () => (
<Router>
<Suspense fallback={<div>Loading...</div>}>
<Switch>
<Route exact path="/" component={Home}/>
<Route path="/about" component={About}/>
</Switch>
</Suspense>
</Router>
);
React.lazy()는 import()구문을 반환하는 콜백함수를 인자로 받는다. 동적 불러오기로 불러와지는 모듈은 1. ReactComponent를 포함하며 2. default export를 가진 모듈이어야 한다. 그리고 불러온 컴포넌트를 반환한다.
React.lazy로 불러온 컴포넌트는 단독으로 쓰일 수 없고, React.Suspense 컴포넌트로 하위에서 렌더링되어야 한다.
Suspense 컴포넌트는 fallback prop을 필수로 가진다. fallback prop은 로딩 표시기로 사용할 컴포넌트를 받는다. 이전글에 자세히 설명해놓았다.
React.lazy는 SSR에서 작동하지 않는다. SSR 웹 앱에서 코드 분할을 하고 싶다면@loadable/component라이브러리를 사용해야한다. 이는 React 공식문서에서도 권장하는 바이다.