리액트로 진행한 프로젝트을 라이트하우스로 돌려봤고 그 중 나온 권장 사항이 사용하지않는 자바스크립트 줄이기였다. 해당 글에서는 위의 이미지와 같이 리액트에서는 code-split을 추천했고 React.lazy()
를 사용하기로 했다.
기존 코드
import HomePage from './HomePage/HomePage';
import MainPage from './MainPage/MainPage';
import LoginPage from './LoginPage/LoginPage';
...
export default function AppRouter() {
return (
...
수정된 코드
const HomePage = lazy(() => import('./HomePage/HomePage'));
const MainPage = lazy(() => import('./MainPage/MainPage'));
const LoginPage = lazy(() => import('./LoginPage/LoginPage'));
...
export default function AppRouter() {
return (
<Suspense fullback={<Spinner />}>
....
</Suspense>
이렇게 코드를 수정했다. React.lazy()
를 사용한다면 <Suspense>
도 필수적으로 사용해야한다. 이때 fullback안의 요소가, 비동기 작업이 자식 컴포넌트에서 처리되기 전에 보이게 된다.
이를 사용하여 번들의 크기를 줄이고, 초기 렌더링에서 사용되지 않는 컴포넌트를 불러오는 작업을 지연시킬 수 있다.
어떤 차이점이 있는지 궁금해 찾아보니 What are the differences between React.lazy and @loadable/components?라는 글을 발견했고 위와 같은 표를 확인할 수 있었다.
SSR에서는 React.lazy
를 사용할 수 없다.
<Suspense/>
의 경우 React.lazy()
에서는 필수적이었던 반면에 @loadbale/component
에서의 경우 선택적으로 사용할 수 있다고 한다.
@loadbale/component
에서는 Library Splitting을 render props를 사용해 지원한다고 한다.
import loadable from '@loadable/component'
const Moment = loadable.lib(() => import('moment'))
function FromNow({ date }) {
return (
<div>
<Moment fallback={date.toLocaleDateString()}>
{({ default: moment }) =>
moment(date).fromNow()}
</Moment>
</div>
)
}
import loadable from '@loadable/component'
const AsyncPage = loadable(props =>
import(`./${props.page}`))
function MyComponent() {
return (
<div>
<AsyncPage page="Home" />
<AsyncPage page="Contact" />
</div>
)
}
이번 프로젝트는 CSR이었기에 lazy()를 사용하였으나 다음에는 SSR에서 @loadbale/component를 사용해보려고한다. 또 3번도 three.js를 쓸 때 번들이 커서 라이트하우스에 자꾸 걸리는게 마음에 걸렸는데 이를 사용하면 해결할 수 있을 것 같아 다음 프로젝트에서 사용해보려고 한다!
그 외 참고글
https://evan6-6.tistory.com/110
https://lakelouise.tistory.com/327