본문 바로가기

react

[리액트를 다루는 기술] 19장 코드 스플리팅

코드 스플리팅

 

- 리액트 애플리케이션의 번들 크기를 줄이기 위해 사용하는 기술

- 리액트 프로젝트를 완성하여 사용자에게 제공할 때는 빌드 작업을 거쳐서 배포

- 웹팩(webpack) 

  -> 별도의 설정을 하지 않으면 프로젝트에서 사용중인 모든 자바스크립트 파일이 하나의 파일로 합쳐지고, 모든 CSS 파일도 하나의 파일로 합쳐짐 

  -> 파일 크기가 매우 커져 사용자 경험이 안 좋아지고 트래픽도 많이 나옴 

  -> 코드 비동기 로딩으로 해결

 

 

19.1 자바스크립트 함수 비동기 로딩

 

- 일반 자바스크립트 함수 스플리팅

 

notify.js

export default function notify() {
    alert('안녕하세요!');
}

 

src/App.js

import logo from './logo.svg';
import './App.css';
import notify from './notify';

function App() {

  const onClick = () => {
    notify();
  };

  return (
   <div className="App">
      <header className="App-header">
        <img src={logo} className="App-logo" alt="logo" />
        <button onClick={onClick}>Hello React!</button>
      </header>
   </div>
  );
}

export default App;

 

- 빌드시 notify 코드가 main 파일 안에 들어가게 됨 

 

src/App.js

- import를 상단에서 하지 않고 import() 함수 형태로 메서드 안에서 사용하면, 파일을 따로 분리시켜서 저장

- Hello React!를 클릭하는 시점에 새로운 자바스크립트 파일을 불러옴

- 불러온 파일의 내용을 확인해보면 notify에 관련된 코드만 들어 있음 

import logo from './logo.svg';
import './App.css';

function App() {

  const onClick = () => {
    import('./notify').then(result=>result.default());
  };

  return (
   <div className="App">
      <header className="App-header">
        <img src={logo} className="App-logo" alt="logo" />
        <button onClick={onClick}>Hello React!</button>
      </header>
   </div>
  );
}

export default App;

 

 

19.2 React.lazy와 Suspense를 통한 컴포넌트 코드 스플리팅

 

19.2.1 React.lazy와 Suspense 사용하기 

 

- React.Lazy와 Suspense를 사용하면 코드 스플리팅을 하기 위해 state를 따로 선언하지 않고도 간편하게 컴포넌트 코드 스플리팅 가능

 

React.Lazy

 

- 컴포넌트를 렌더링하는 시점에서 비동기적으로 로딩할 수 있게 해주는 유틸 함수 

 

ex)

const SpliteMe = React.Lazy(()=> import('./SpliteMe'));

 

Suspense 

 

- 리액트 내장 컴포넌트로서 코드 스플리팅된 컴포넌트를 로딩하도록 발동시킬 수 있고, 로딩이 끝나지 않았을 때 보여줄 UI 설정 

 

ex)

import {Suspense} from 'react';

(...)
<Suspense fallback={<div>loading...</div>}>
	<SpliteMe />
</Suspense>

 

 

SplitMe.js

const SplitMe = () => {
    return <div>SpliteMe</div>
};

export default SplitMe;

 

App.js

import {useState, Suspense, lazy} from 'react';
import logo from './logo.svg';
import './App.css';
const SpliteMe = lazy(() => import('./SpliteMe'));

function App() {
  const [visible, setVisible] = useState(false);
  const onClick = () => {
    setVisible(true);
  };

  return (
   <div className="App">
      <header className="App-header">
        <img src={logo} className="App-logo" alt="logo" />
        <button onClick={onClick}>Hello React!</button>
        <Suspense fallback={<div>loading...</div>}>
          {visible&&<SpliteMe/>}
        </Suspense>
      </header>
   </div>
  );
}

export default App;

 

 

 

 

 

19.2.2 Loadable Components를 통한 코드 스플리팅

 

Loadable Components

 

- 코드 스플리팅을 편하게 하도록 도와주는 서드파티 라이브러리 

- 서버 사이드 렌더링 지원 

- 렌더링하기 전에 필요할 때 스프리팅된 파일을 미리 불러올 수 있는 기능 

 

npm install @loadable/component

 

 

App.js

import {useState} from 'react';
import logo from './logo.svg';
import './App.css';
import loadable from '@loadable/component';

const SpliteMe = loadable(()=>import('./SpliteMe'),{
  fallback:<div>loading...</div>
});

function App() {
  const [visible, setVisible] = useState(false);
  const onClick = () => {
    setVisible(true);
  };

  return (
   <div className="App">
      <header className="App-header">
        <img src={logo} className="App-logo" alt="logo" />
        <button onClick={onClick}>Hello React!</button>
        {visible&&<SpliteMe/>}
      </header>
   </div>
  );
}

export default App;

 

 

- 컴포넌트를 미리 불러오는(preload) 방법 

 

App.js

- 마우스 커서를 Hello React! 위에 올리기만 해도 로딩 시작 

import {useState} from 'react';
import logo from './logo.svg';
import './App.css';
import loadable from '@loadable/component';

const SpliteMe = loadable(()=>import('./SpliteMe'),{
  fallback:<div>loading...</div>
});

function App() {
  const [visible, setVisible] = useState(false);
  const onClick = () => {
    setVisible(true);
  };

  const onMouseOver = () => {
    SpliteMe.preload();
  };

  return (
   <div className="App">
      <header className="App-header">
        <img src={logo} className="App-logo" alt="logo" />
        <button onClick={onClick} onMouseOver={onMouseOver}>Hello React!</button>
        {visible&&<SpliteMe/>}
      </header>
   </div>
  );
}

export default App;