이번엔 react-router-dom에서 제공하는 lazy프로퍼티에 대해 알아보자.
트리쉐이킹을 위해 LazyLoading을 적용하면서 기본 리액트가 제공하는 lazy와 Suspense를 이용한 방법과 router에서 제공하는 lazy를 각각 적용하며 비교해본 결과 router에서 제공하는 방식이 미약하지만 더 크게 최적화를 이룰 수 있었다.
export const loader = () => {}
export const action = () => {}
const Service = () => {
return <> ... </>
}
export default Service
위와 같은 컴포넌트가 존재하고 이 컴포넌트에 lazy loading을 적용해보자
<Route element={<Layout/>}>
<Route path='/' element={<Home/>} /> // 홈 화면은 lazy적용 x
<Route
path='/service'
lazy={async() => {
const module = await import('컴포넌트경로')
return {
Component: module.default,
loader: module.loader,
action: module.action
}
}
}
/>
</Route>
이게 전부다.
loader, action, Component까지 전부 한번에 lazy loading을 적용할 수 있다.
fallback같은 경우는 따로 제공하지 않아서 전역적으로 컴포넌트 내부에서 useNavigation훅을 통해 state가 로딩일경우 로딩컴포넌트를 제공하도록 구현할 수 있다.
라우트에서 각각 lazy loading을 적용하고 어떤 컴포넌트는 컴포넌트만 가지고, 어떤 경우는 로더를 포함하는 등 여러 케이스가 존재할 수 있다.
따라서 동적으로 import path만 입력해서 알아서 존재하는 컴포넌트,loader,action을 return하도록 다이나믹한 커스텀함수를 만들어 쓸 수 있다.
type PathType = {
readonly default: () => JSX.Element
readonly ErrorBoundary?: ComponentType | null
laoder?: LoaderFunction
action?: ActionFunction
}
type LazyResult = () => Promise<{
readonly default: () => JSX.Element
readonly ErrorBoundary?: ComponentType | null
}>
}
const getLazyLoader = (path : PathType) => {
const lazyReturn: LazyRouteFunction<NonIndexRouteObject> = async() => {
const module: LazyResult = await path()
return {
Component: module?.default,
loader: module?.loader,
action: module?.action,
ErrorBoundary: module?.ErrorBoundary
}
}
return lazyReturn
}
<Route element={<Layout/>}>
<Route path='/' element={<Home/>} /> // 홈 화면은 lazy적용 x
<Route
path='/service'
lazy={
getLazyLoader(
async() => await import('컴포넌트 절대경로'))
}
/>
</Route>
다이나믹 레이지로더 적용 결과 라우트안에서 lazy load가 필요한 컴포넌트를 loader, action을 포함해서 적용시킬 수 있다.