- Webpack, Rollup, Browerify같은 툴을 사용해 여러 파일을 병합한 번들된 파일을 웹페이지에서 로드할 수 있음
ex)
import { add } from './math.js';
console.log(add(16, 26));
export function add(a, b) {
return a + b;
}
function add(a, b) {
return a + b;
}
console.log(add(16, 26));
코드 분할
- 앱의 크기가 커지게 되면 변들의 규모가 커지게 됨
- 특히 크기가 큰 서드파티 라이브러리를 추가하면 앱의 크기가 커져 로드 시간이 길어지기도 함
- 번들이 커지는 것을 방지하기 위해 여러 번들을 동적으로 만들고 불러오는 것이 필요함
- 코드 분할을 통해 앱을 지연로딩할 수 있게 해주고, 앱 사용자 입장에서는 앱의 성능 향상이 되게 해줌
import()
- import를 지연시키는 방법을 통해 앱에 코드 분할을 도입할 수 있음
import("./math").then(math => {
console.log(math.add(16, 26));
});
- 웹팩이 이 구문을 만나게 되면 코드 분할이 가능함
React.lazy
- React.lazy 함수를 사용하면 컴포넌트가 렌더링 될 때 나머지 번들을 불러오게 됨
- React.lazy 함수에서는 동적 import를 호출하는 함수를 인자로 가지고, 이 함수는 React 컴포넌트를 default export로 가져야 함
const OtherComponent = React.lazy(() => import('./OtherComponent'));
- lazy 컴포넌트는 예비 컨텐츠를 보여주는 suspense 컴포넌트 안에서 렌더링 되야 함
import React, { Suspense } from 'react';
const OtherComponent = React.lazy(() => import('./OtherComponent'));
const AnotherComponent = React.lazy(() => import('./AnotherComponent'));
function MyComponent() {
return (
<div>
<Suspense fallback={<div>Loading...</div>}>
<OtherComponent />
<AnotherComponent />
</Suspense>
</div>
);
fallback을 피하는 법
- lazy 컴포넌트를 로딩하게 되면 기존에 존재하던 Suspense 내부의 컴포넌트들까지 일시적으로 보이지 않는 문제가 발생하게 됨
import React, { Suspense } from 'react';
import Tabs from './Tabs';
import Glimmer from './Glimmer';
const Comments = React.lazy(() => import('./Comments'));
const Photos = React.lazy(() => import('./Photos'));
function MyComponent() {
const [tab, setTab] = React.useState('photos');
function handleTabSelect(tab) {
setTab(tab);
};
return (
<div>
<Tabs onTabSelect={handleTabSelect} />
<Suspense fallback={<Glimmer />}>
{tab === 'photos' ? <Photos /> : <Comments />}
</Suspense>
</div>
);
}
Error boundaries
- 에러 처리가 필요한 경우 Error Boundary를 Suspense 위에 감싸 네트워크 문제가 생겼을 때 에러를 표시할 수 있음
import React, { Suspense } from 'react';
import MyErrorBoundary from './MyErrorBoundary';
const OtherComponent = React.lazy(() => import('./OtherComponent'));
const AnotherComponent = React.lazy(() => import('./AnotherComponent'));
const MyComponent = () => (
<div>
<MyErrorBoundary>
<Suspense fallback={<div>Loading...</div>}>
<section>
<OtherComponent />
<AnotherComponent />
</section>
</Suspense>
</MyErrorBoundary>
</div>
);
Route-based code splitting
- 앱의 코드 분할을 시도하 경우 라우트에서부터 코드 분할을 하는 것을 권장
페이지 전환시 웹 페이지를 불러오는 시간은 필연적으로 발생하게 됨
보통 페이지를 한번에 렌더링하기 때문에 렌더링 동안 다른 요소와도 상호작용할일이 없음
import React, { Suspense, lazy } from 'react';
import { BrowserRouter as Router, Routes, Route } from 'react-router-dom';
const Home = lazy(() => import('./routes/Home'));
const About = lazy(() => import('./routes/About'));
const App = () => (
<Router>
<Suspense fallback={<div>Loading...</div>}>
<Routes>
<Route path="/" element={<Home />} />
<Route path="/about" element={<About />} />
</Routes>
</Suspense>
</Router>
);
Named Exports
- default exports 이외에 named exports를 사용하고자 하면 default로 이름을 재정의한 중간 모듈을 생성해 주어야 함
export const MyComponent = ;
export const MyUnusedComponent = ;
export { MyComponent as default } from "./ManyComponents.js";
import React, { lazy } from 'react';
const MyComponent = lazy(() => import("./MyComponent.js"));