Lazy Loading & Code Splitting
September 08, 2020
How to set up lazy loading components in React
리액트 자바스크립트 코드 분할 & 레이지 로딩 적용 성능 최적화하기
레이지 로딩(lazy loading)
레이지 로딩은 필요 시점까지 객체의 초기화를 연기시키기 위해 컴퓨터 프로그래밍에 흔히 사용되는 디자인 패턴의 하나로 적절하게 사용될 경우 프로그램의 운영 차원에서 효율적이다.
코드 분할 Code Splitting
앱이 커지면 번들 사이즈도 커진다. 특히 큰 규모의 서드 파티 라이브러리를 추가할 때 실수로 앱이 커져서 로드 시간이 길어진다.
대부분의 경우 사용자는 적어도 처음에는 전체 웹 페이지를 보지 못한다.
이러한 경우 이러한 구성 요소를 렌더링하면 응용 프로그램의 성능이 저하 될뿐만 아니라 많은 리소스가 낭비된다. (특히 이미지 나 유사한 데이터를 많이 사용하는 콘텐츠가있는 경우)
번들이 거대해지는 것을 방지하기 위한 좋은 해결방법은 번들을 나누는 것이다. 코드 분할은 런타임에 여러 번들을 동적으로 만들고 불러오는 것으로 Webpack, Rollup과 Browserify (factor-bundle) 같은 번들러가 지원하는 기능이다.
코드 분할은 lazy loading을 통해 앱 사용자에게 획기적인 성능 향상을 할 수 있다. 앱의 코드 양을 줄이지 않고도 사용자가 필요하지 않은 코드를 불러오지 않게 하며 앱의 초기화 로딩에 필요한 비용을 줄일 수 있다.
React.lazy
CRA
before
import OtherComponent from "./OtherComponent"
after
const OtherComponent = React.lazy(() => import("./OtherComponent"))
MyComponent가 처음 렌더링 될 때 OtherComponent를 포함한 번들을 자동으로 로드.
React.lazy는 동적 import()를 호출하는 함수를 인자로 갖는다.
lazy 컴포넌트는 Suspense 컴포넌트 하위에서 렌더링되어야 하며, Suspense
는 lazy 컴포넌트가 로드되길 기다리는 동안 로딩 화면과 같은 컨텐츠를 보여줄 수 있다.
import React, { Suspense } from "react"
const OtherComponent = React.lazy(() => import("./OtherComponent"))
const AnotherComponent = React.lazy(() => import("./AnotherComponent"))
function MyComponent() {
return (
<div>
{/* fallback 로딩시 보여줄 컨텐츠 */}
<Suspense fallback={<div>Loading...</div>}>
<section>
<OtherComponent />
<AnotherComponent />
</section>
</Suspense>
</div>
)
}
fallback
: 컴포넌트가 로드될 때까지 기다리는 동안 렌더링하려는 React 엘리먼트
하나의 Suspense 컴포넌트로 여러 lazy 컴포넌트를 감쌀 수도 있다.
Route-based code splitting
라우트 기반 코드분할 설정하기
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-lazyload Modules
import React from "react"
import LazyLoad from "react-lazyload"
import MyComponent from "./MyComponent"
const App = () => {
return (
<LazyLoad height={200}>
<img src="tiger.jpg" />
</LazyLoad>
<LazyLoad>
<MyComponent />
</LazyLoad>
)
}
https://www.npmjs.com/package/react-lazyload
SSR Code Splitting
@loadable/components
서버 사이드 렌더링 앱에서는 Lodable Component 를 사용
SSR loadable component example
import loadable from "@loadable/component"
const OtherComponent = loadable(() => import("./OtherComponent"))
function MyComponent() {
return (
<div>
<OtherComponent />
</div>
)
}
Reference