코드 스플리팅 - react

bicco2·2023년 4월 25일
0
post-thumbnail

Suspense 컴포넌트 (+ Outlet)


사용 정리

  1. _layout.tsx 에 설정 후 사용 >> 상위 컴포넌트 레이아웃화
  2. <Suspense> 컴포넌트와 결합해서 사용해 로드 상태 처리 구현
    (❓서버 사이드 렌더링에서는 사용 불가? >> 이 경우에는 loadable-components 같은 라이브러리 사용 )
  3. 제일 상위 컴포넌트를 GlobalLayout 로 설정 후 children(<Outlet>)처리로 중첩 라우팅
    (react-router-dom)
// _layout.tsx
import { Suspense } from "react";
import { Outlet } from "react-router-dom";

export default function Layout() {
  return (
    <Suspense fallback="loading...">
      <Outlet />
    </Suspense>
  );
}
  • 상위 컴포넌트를 위와 같이 구성하면
<Route path="/" element={<Dashboard />}>
  <Route
    path="messages"
    element={<DashboardMessages />}
  />
  <Route path="tasks" element={<DashboardTasks />} />
</Route>
  • 아래와 같은 중첩 라우팅 이용가능.
  • 두번째 Route가 children으로 들어간다. (<Outlet>)

사용 이유

  • javascript가 페이로드 전송시 속도가 느리면 페이지 완료 시간이 길어진다.
  • 이때 로딩을 보여줌으로써 사용자에게 페이지 상태(네트워크)를 알리거나 코드 분할이 가능해진다.
    *** 코드 스플리팅이란?
    : React 앱을 작은 조각으로 나눠 필요한 경우에만 불러오는 기술
  • 보통 Suspense 구성 요소와 함께 React.lazy를 같이 사용한다.

*** 로딩시 에러 처리 - https://legacy.reactjs.org/docs/error-boundaries.html



React.lazy 함수

Before

import OtherComponent from './OtherComponent';

After

const OtherComponent = React.lazy(() => import('./OtherComponent'));


특징

  • React 컴포넌트를 default export로 가진 모듈 객체가 이행되는 Promise를 반환해야 한다.
    (❓컴포넌트는 원래 promise를 반환하진 않는다.
    하지만 React.lazy를 사용하면 default export로 가진 모듈 객체가 Promise로 감싸진다.
    따라서 import될 컴포넌트가 모듈 객체로 이행될때까지 대기)
  • 무조건 Suspense 컴포넌트 하위에서 렌더링 되야한다.
  • 동적 렌더링이기 때문에 loading이 필수적이다.
  • 렌더링 시점에 모듈을 로드한다.

사용 이유

  • import가 동적 렌더링이 가능해진다.
  • 코드 분할에 사용한다.
  • 초기 로딩시간을 줄일 수 있다. (성능 향상)
  • 브라우저가 필요할 때 컴포넌트를 로드하는 것을 가능하게 한다.


최종 라우터 코드

// Routes.tsx

import { lazy } from "react";
import GlobalLayout from "./pages/_layout";

const SignInPage = lazy(() => import("./pages/signin"));
const SignUpPage = lazy(() => import("./pages/signup"));
const HomePage = lazy(() => import("./pages/home"));
const TodoPage = lazy(() => import("./pages/todo"));

export const routes = [
  {
    path: "/",
    element: <GlobalLayout />,
    children: [
      { index: true, element: <HomePage /> },
      { path: "/signin", element: <SignInPage /> },
      { path: "/signup", element: <SignUpPage /> },
      { path: "/todo", element: <TodoPage /> },
    ],
  },
];
  • element에 상위 컴포넌트 layout 전달
  • 상위 컴포넌트 레이아웃화(거기에 <Suspense>로 감싸서 loading 처리)
  • children에 하위 컴포넌트 전달 : <Outlet>에서 처리
  • React.lazy를 통한 성능 향상 및 동적 렌더링시 loading 처리

** index 속성은 경로를 설정하진 않지만 기본 하위 경로로 자동 설정될지를 나타낸다.



참고

chuck.js 파일이란 ?

React 애플리케이션을 개발할 때, 일반적으로 webpack과 같은 번들러를 사용하여 여러 개의 JavaScript 파일을 하나로 묶어서 처리합니다. 이 과정에서 webpack은 번들링된 JavaScript 파일을 청크(chunk) 단위로 분리하여 빌드합니다.
React 애플리케이션이 로딩될 때, webpack에서 빌드한 청크(chunk) 파일들이 다운로드되고 로딩되면서 애플리케이션이 실행됩니다. 이때 보통 chunk.js 확장자를 가진 파일들이 다운로드되는데, 이 파일들은 웹팩에서 빌드한 청크 파일들을 포함하고 있습니다.
따라서 chunk.js 파일들은 웹팩에서 애플리케이션을 빌드할 때 생성되는 파일로, 웹팩이 번들링한 모듈들을 포함합니다. 이 파일들을 로딩하는 것은 React 애플리케이션의 초기 구동 속도를 향상시키는 데 도움이 됩니다.

웹팩에서 코드 스플리팅을 설정하면, 빌드 시점에서 생성된 청크 파일들이 렌더링 시점에 로드되어 렌더링 속도를 개선할 수 있습니다.
=> cra로 프로젝트 생성하면 프로덕션 빌드에서 코드 스플리팅을 자동으로 설정해 chuck 파일을 로직과 함께 빌드함

CRA에서는 webpack과 같은 빌드 도구를 사용하여 코드 스플리팅을 구현합니다. React.lazy()와 Suspense를 사용하여 동적으로 모듈을 로드하면, 해당 모듈의 청크 파일이 필요할 때 자동으로 로딩되며, 필요한 시점에 렌더링됩니다. 이러한 코드 스플리팅 방식은 불필요한 로딩 시간을 최소화하여 성능을 향상시키는 데 도움을 줍니다.


profile
FE 개발자다?

0개의 댓글