All Articles

[React] Code Splitting

  • 런타임에 번들을 동적으로 생성하고 불러오는 것
  • 앱의 초기 구동 시에 모든 컴포넌트의 리소스를 다 다운받을 필요는 없다
  • 리소스를 컴포넌트 단위로 분리시켜 필요한 것들만 다운로드 받을 수 있도록 함
  • 당장 필요치 않은 코드 불러오지 X ⇒ 최초 로딩 비용 ↓

React.lazySuspense 는 아직 SSR 불가능하다고 한다. Loadable Components 같은 모듈 사용해야 함

React.lazy

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

Route-based code splitting

특정 route에 대해 필요없는 코드들까지 한번에 로드해버리는 것을 막기 위해 가장 좋은 방법이 router 에서 code splitting 하는 방식이라고 한다.

유저가 다른 페이지로 넘어가 때에만 그 페이지를 asynchronous하게 로딩

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>
);

근데 RootRouter에서 lazy loading을 하게 되면 어차피 App 렌더링 시 RootRouter 렌더링 ⇒ 결국 거기서 lazy loading 하고 있는 컴포넌트들 다 렌더링 ⇒ 결국 최초 로딩 시 렌더링 되는 것들은 똑같이 한꺼번에 렌더링 될 거라고 생각했는데 아니었다. 루트에 접근했을 때 해당 컴포넌트가 레이지 로드 되는 방식인듯 ! Route 종류가 많을 때 엄청 유용할 것 같다. live-commerce/react 레포에서 이렇게 쓰고 있다.

Suspense

  • 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>
      <Suspense fallback={<div>Loading...</div>}>
        <section>
          <OtherComponent />
          <AnotherComponent />
        </section>
      </Suspense>
    </div>
  );
}

Webpack ⇒ dynamic import

원래 방식대로 하지 않고 필요할 때 함수 형식으로 import 한다

사이즈가 큰, 로딩에 오래걸리는 컴포넌트에는 이렇게 쓰는 것도 괜찮을 듯. 그런데 lazy 가 훨 깔끔함

if(videoComponent) {
  import('./component/video')
    .then(video => {
        video.loadElements()
    })
    .catch(e => console.log(e))
}

Vue에선 이렇게 했었다

  • 라우터에서의 컴포넌트 import 부분을 함수로 변경해준다
  • 간단하긴 하군…
// before
component: MyProfile

// after
component: () => import( "./components/MyProfile.vue" )