리액트 프로젝트를 완성하여 사용자에게 제공 될 때는 빌드 작업을 거쳐서 배포해야한다
이 작업은 웹팩이 담당하며 모든 파일 하나의 파일로 합쳐진다. CRA로 프로젝트를 빌드 할 경우 최소 두개 이상의 자바스크립트 파일 생성, CRA의 기본 웹팩 설정엔 여러 파일간에 공유된 파일을 자동으로 분리 시켜 캐싱의 효과를 누릴 수 있다.
리액트 프로젝트를 생성 하고 $ yarn build
하면 build/static 디렉터리에 자바스크립트 파일 여러개가 만들어진다.
파일 이름을 보면 '7b7b7f24'같은 해시 값이 포함되어 있는데 이 값은 빌드 하는 과정에서 해당 파일의 내용에 따라 생성, 이를 통해 브라우저가 새로 파일을 받아야 할지 말지를 알수 있다.
이렇게 파일을 분리 하는 작업을 코드 스플리팅 이라 하면 프로젝트에 기본탑재된 SplitChunks 기능을 통한 코드 스플리팅은 단순히 효율적인 캐싱 효과만 있다
예로 A,B,C 로 구성 된 싱글페이지 애플리케이션을 개발 한다고 가정 했을때 사용자가 A페이지에 방문 했다면 B,C 페이지에서 사용되는 컴포넌트 정보는 필요하지 않다. 실제로 B 혹은 C 페이지로 이동 하려고 할때만 필요 하지만 리액트는 별도로 설정 하지 않으면 A,B,C 에 대한 컴포넌트 코드가 한 파일에 저장되어 버린다. 로딩이 길어지고 트래픽도 많이 나온다.
이러한 문제점을 해결해 줄수있는 방법이 비동기 로딩. 이 또한 코드 스플리팅 방법중 하나. 코드 비동기 로딩을 통해 자바스크립트 함수, 객체, 컴포넌트를 필요한 시점에서 사용 할수있다.
import logo from './logo.svg';
import './App.css';
// import notify from './notify';
function App() {
const onClick = () => {
// notify();
import('./notify').then(result => result.default()); //import를 상단에 하지 않고 import() 함수 형태로 메서드 안에서 사용 하면 파일을 따로 분리 시켜 저장, 실제 함수가 필요한 지점에 파일을 불러와 함수를 사용 할수 있다.
};
return(
<div className='App'>
<header className='App-header'>
<img src={logo} className="App-logo" alt="logo"/>
<p onClick={onClick}>Hello React</p>
</header>
</div>
)
}
export default App;
import 를 함수로 사용하면 Promise를 반환하지만 아직 표준자바스크립트는 아니지만 웹팩에서 지원 하고 있으므로 별도의 설정없이 프로젝트에서 사용 가능.
const SplitMe = React.lazy(() => import('./SplitMe'));
import { Suspense } from 'react';
<Suspense fallback={<div>loading...</div>}>
<SplitMe />
</Suspense>
코드 스프리팅을 편하게 해주는 서드파티 라이브러리. 서버 사이드 렌더링을 지원한다. 렌더링 하기전 스플리팅 된 파일을 미리 불러올수 잇다.
서버 사이드 렌더링 이랑 웹 서비스 초기 로딩 속도 개선, 캐싱 및 검색 엔진 최적화를 가능하게 한다.서버 사이드 렌더링을 사용하면 웹 서비스 초기 렌더링을 사용자의 브라우저가 아닌 서버쪽에서 처리. 사용자는 렌더링한 html 결과물을 받아와서 그대로 사용하기 때문에 초기 로딩 속도 개선되고 검색엔진에서 크롤링 할때도 문제가 없다.
yarn add @loadable/component
를 설치 한다.
// loadable
const SplitMe = loadable(() => import('./SplitMe'), {
fallback: <div>loading...</div>
});
function App() {
const [visible, setVisible] = useState(false);
const onClick = () => {
setVisible(true);
};
const onMouseOver = () => { //커서를 올리기만 해도 로딩이 시작된다, 나중에 사용자에게 더 좋은 경험을 제공
SplitMe.preload();
}
return (
<div className='App'>
<header className='App-header'>
<img src={logo} className="App-logo" alt='logo'/>
<p onClick={onClick} onMouseOver={onMouseOver}>Hello React!</p>
{visible && <SplitMe />}
</header>
</div>
)
}
export default App;
Loadable Component는 미리 불러오는 기느 외에도 타임아웃, 로딩 UI 딜레이, 서버사이드 렌더링 호환등 다양한 기능을 제공.