findmypiece.tistory.com/16?category=966881
위에서 포스팅 했듯이 리액트 빌드시 웹팩에서 기본적인 코드 스플리팅은 해주지만
프로젝트에서 작성하는 코드들도 한 파일로 합쳐지지 않도록 코드 스플리팅이 필요하다.
그 방법으로 컴포넌트 자체를 지연로딩 하는 방법이 있다.
이를 통해 초기 렌더링에 필요없는 컴포넌트들은 로딩 하지 않아 로딩시간도 짧아지고
트래픽도 절약할 수 있다.
그리고 이렇게 지연로딩 되는 컴포넌트는 웹팩 빌드시
별도 파일로 합쳐지기 때문에 브라우저 캐시 효율성도 증가한다.
이는 기본적으로 ES6에 추가된 dynamic import 문법을 활용하는 것인데
Promise 기반으로 import를 동적으로 수행할 수 있게 해준다.
다만 이것을 활용하려면 컴포넌트 에서 매번 state를 선언해서
지연로딩으로 읽어온 컴포넌트를 넣는 방식으로 구현해야 한다.
조건부 렌더링을 구현하려면 state 와 같은 가변적인 상태가 필요하기 때문.
그런데 리액트 16.6 버전부터 도입된 React.lazy와 Suspense를 활용하면
state를 선언하지 않고도 간편하게 동적 컴포넌트 지연로딩을 구현할 수 있다.
React.lazy 는 유틸 함수이고 Suspense는 리액트 내장 컴포넌트인데
React.lazy는 컴포넌트를 렌더링 하는 시점에 비동기적으로 로딩할 수 있게 해주고
Suspense는 이렇게 비동기적으로 로딩되는 동안 보여줄 UI를 설정할 수 있게 해준다.
구현은 대략 아래와 같이 하면 되고
CounterContainer 컴포넌트가 실제 렌더링 될때 import 가 수행되게 된다.
import React, {useState, Suspense} from 'react';
import TodosContainer from "./containers/TodosContainer";
const CounterContainer = React.lazy(() => import('./containers/CounterContainer'));
const App = () => {
const [viewCounter, setViewCounter] = useState(false);
const onClick = () => {
setViewCounter(true);
}
return (
<div>
<button type="button" onClick={onClick}>카운터세기</button>
<Suspense fallback={<div>loading...</div>}>
{viewCounter && <CounterContainer />}
{viewCounter && <hr />}
</Suspense>
<TodosContainer />
</div>
);
};
export default App;
그런데 리액트 버전 문제인지 내가 설치한 리액트 버전(17.0.1)에서는 제대로 동작하지 않았다.
그래서 나는 Loadable Components를 사용해서 컴포넌트 지연로딩을 구현했다.
이는 컴포넌트 지연로딩을 도와주는 서드파티 라이브러리로 React.lazy/Suspense 와 다르게
서버 사이드 렌더링을 지원한다. 리액트 공식문서에서도 서버 사이드 렌더링을 할 경우
Loadable Components 를 사용하도록 권장한다고 한다.
또한 서드파티 라이브러리답게 컴포넌트가 렌더링 되지 않더라도
파일을 미리 로딩할 수 있는 추가 기능도 제공한다.
그냥 처음부터 이걸 쓸 걸 그랬다..
우선 Loadable Components 라이브러리를 설치해야 한다.
yarn add @loadable/component
사용법은 대략 아래와 같다.
import React, {useState} from 'react';
import loadable from '@loadable/component';
import TodosContainer from "./containers/TodosContainer";
const CounterContainer = loadable(
() => import('./containers/CounterContainer'),
{fallback: <div>loading</div>});
const App = () => {
const [viewCounter, setViewCounter] = useState(false);
const onClick = () => {
setViewCounter(true);
}
const onMouseOver = () => {
CounterContainer.preload();
}
return (
<div>
<button type="button" onClick={onClick} onMouseOver={onMouseOver}>카운터세기</button>
{viewCounter && <CounterContainer />}
{viewCounter && <hr />}
<TodosContainer />
</div>
);
}
export default App;
React.lazy 와 비슷한데 Suspense 컴포넌트를 별도 정의할 필요없이 함수 사용시 옵션으로 설정할 수 있다.
옵션인만큼 fallback 설정은 필요없다면 정의하지 않으면 된다.
React.lazy/Suspense 때와는 다르게 버튼에 onMouseOver 이벤트가 추가되었는데
preload() 를 통해 렌더링 전에 파일을 미리 로딩할 수 있다.
'Frontend > ReactJS' 카테고리의 다른 글
외부 js, css 파일 사용하기 (0) | 2021.03.04 |
---|---|
useEffect (0) | 2021.03.04 |
코드 스플리팅(spliting) (0) | 2021.03.03 |
json-server 를 이용한 테스트용 api 서버 구성 (0) | 2021.03.03 |
리액트 프로젝트 디렉토리 구조 (0) | 2021.03.03 |