[React] Code Spliting

강은비·2022λ…„ 1μ›” 19일
0

React

λͺ©λ‘ 보기
25/36

react μŠ€ν„°λ””μ—μ„œ λ¦¬μ•‘νŠΈλ₯Ό λ‹€λ£¨λŠ” κΈ°μˆ μ΄λΌλŠ” 책을 μ„ μ •ν–ˆκ³  이 책을 읽고 배운 것을 λ°”νƒ•μœΌλ‘œ μž‘μ„±λ˜μ—ˆλ‹€.


🧩 μ½”λ“œ μŠ€ν”Œλ¦¬νŒ…μ΄λž€?

  • 말 κ·ΈλŒ€λ‘œ μ½”λ“œλ₯Ό λΆ„λ¦¬ν•˜λŠ” 것을 λ§ν•œλ‹€.
  • μ›ΉνŒ©μ—μ„œ λ³„λ„μ˜ 섀정을 ν•˜μ§€ μ•ŠμœΌλ©΄ ν”„λ‘œμ νŠΈμ—μ„œ μ‚¬μš© 쀑인 λͺ¨λ“  μžλ°”μŠ€ν¬λ¦½νŠΈ 파일이 ν•˜λ‚˜μ˜ 파일(main)둜 합져진닀.
  • μ• ν”Œλ¦¬μΌ€μ΄μ…˜μ˜ 규λͺ¨κ°€ 컀질수둝 main 파일 크기도 μ»€μ§€λŠ”λ° 그러면 νŽ˜μ΄μ§€ λ‘œλ”© μ‹œ μ§€κΈˆ λ‹Ήμž₯ ν•„μš”ν•˜μ§€ μ•Šμ€ μ½”λ“œλ„ μ „λΆ€ λΆˆλŸ¬μ™€ νŽ˜μ΄μ§€ λ‘œλ”© μ‹œκ°„μ΄ κΈΈμ–΄μ Έ μ‚¬μš©μž κ²½ν—˜λ„ μ•ˆ 쒋아지고 νŠΈλž˜ν”½λ„ μ¦κ°€ν•œλ‹€.
  • code spliting을 μ μš©ν•˜λ©΄ λ‹Ήμž₯ ν•„μš”ν•˜μ§€ μ•Šμ€ μ½”λ“œλŠ” λΆ„λ¦¬μ‹œμΌœ λ‚˜μ€‘μ— ν•„μš”ν• λ•Œ λΆˆλŸ¬μ™€μ„œ μ‚¬μš©ν•  수 μžˆλ‹€. (μ½”λ“œ 비동기 λ‘œλ”©) => νŽ˜μ΄μ§€ λ‘œλ”© μ‹œκ°„μ΄ κ°œμ„ λœλ‹€.

πŸ“ ν•¨μˆ˜ μ½”λ“œ μŠ€ν”Œλ¦¬νŒ…

dynamic import

// notify.js
export default function notify(){
    alert("μ•ˆλ…•ν•˜μ„Έμš”!");
}
// App.js
// import notify from "./notify";

function App(){
    const onClick = () => {
        import("./notify").then(result => result.default());
        // notify();
    }
    return (
        <button onClick={onClick}>Notify</button>
    );
}
  • 상단에 importλ₯Ό 톡해 nofityλ₯Ό 뢈러였면 notify μ½”λ“œκ°€ main 파일 μ•ˆμ— λ“€μ–΄κ°€κ²Œ λœλ‹€.
  • ν•˜μ§€λ§Œ import() ꡬ문을 μ‚¬μš©ν•˜λ©΄ μ½”λ“œλ₯Ό ν•„μš”ν•œ μ‹œμ μ— λΆˆλŸ¬μ™€ μ‚¬μš©ν•  수 있고 μ½”λ“œλ„ λ”°λ‘œ νŒŒμΌμ„ λΆ„λ¦¬μ‹œμΌœ μ €μž₯λœλ‹€.
    • chunk 파일: μ½”λ“œ μŠ€ν”Œλ¦¬νŒ… μ‹œ μƒμ„±λ˜λŠ” μžλ°”μŠ€ν¬λ¦½νŠΈ 파일
  • import() ꡬ문은 ν”„λ‘œλ―ΈμŠ€ 객체λ₯Ό λ°˜ν™˜ν•˜λŠ”λ° ν”„λ‘œλ―ΈμŠ€ 객체의 λ°˜ν™˜κ°’μ€ 뢈러온 λͺ¨λ“ˆμ΄λ‹€.

πŸ“ μ»΄ν¬λ„ŒνŠΈ μ½”λ“œ μŠ€ν”Œλ¦¬νŒ…

1. state 이용

  • import()λ₯Ό 톡해 μ»΄ν¬λ„ŒνŠΈλ₯Ό ν•„μš”ν•œ μ‹œμ μ— λΆˆλŸ¬μ™€ μ»΄ν¬λ„ŒνŠΈ 자체λ₯Ό state에 λ„£λŠ”λ‹€.
// SplitMe.js
const SplitMe = () => {
    return <div>SplitMe</div>;
}

export default SplitMe;
// App.js
import { Component } from "react";

class App extends Component{
    state = {
        SplitMe: null
    };
    
    handleClick = async () => {
        const loadingModule = await import("./SplitMe");
        this.setState({
            SplitMe: loadingModule.default
        });
    }
    
    
    
    render() {
        const { SplitMe } = this.state;
        return (
            <div>
                <button onClick={handleClick}>Click!</button>
                {SplitMe && <SplitMe/>
            </div>
        );
    }
}

2. React.lazy와 Suspense

React.lazy()

  • μ»΄ν¬λ„ŒνŠΈλ₯Ό λ Œλ”λ§ν•˜λŠ” μ‹œμ μ—μ„œ λΉ„λ™κΈ°μ μœΌλ‘œ λ‘œλ”©ν•  수 있게 ν•΄μ£ΌλŠ” ν•¨μˆ˜
  • import() ꡬ문을 λ°˜ν™˜ν•˜λŠ” μ½œλ°±ν•¨μˆ˜λ₯Ό 인자둜 κ°–λŠ”λ‹€.
  • μ΄λ•Œ import() ꡬ문으둜 λΆˆλŸ¬μ™€μ§€λŠ” λͺ¨λ“ˆμ€ React Componentλ₯Ό ν¬ν•¨ν•˜λ©° default exportλ₯Ό κ°€μ Έμ•Ό ν•œλ‹€.
  • 뢈러온 μ»΄ν¬λ„ŒνŠΈλ₯Ό λ°˜ν™˜ν•œλ‹€.
const SplitMe = React.lazy(() => import("./SplitMe"));

Suspense

  • React.lazy둜 뢈러온 μ»΄ν¬λ„ŒνŠΈλŠ” Suspense μ»΄ν¬λ„ŒνŠΈ ν•˜μœ„μ—μ„œ λ Œλ”λ§λ˜μ–΄μ•Ό ν•œλ‹€.
  • fallback prop둜 μ»΄ν¬λ„ŒνŠΈκ°€ λ‘œλ“œλ˜κΈΈ κΈ°λ‹€λ¦¬λŠ” λ™μ•ˆ λ Œλ”λ§ν•˜λ €λŠ” React elementλ₯Ό μ„€μ •ν•  수 μžˆλ‹€.
// App.js
import { useState, Suspense } from "react";

const SplitMe = React.lazy(() => import("./SplitMe"));

function App(){
    const [visible, setVisible] = useState(false);
    const onClick = () => {
        setVisible(true);
    };
    return (
        <div>
            <button onClick={handleClick}>Click!</button>
            <SusPense fallback={<div>loading...</div>}>
                {visible && <SplitMe/>}
            </Suspense>
        </div>
    );

}

3. Loadable Components

  • @loadable/componentλŠ” μ½”λ“œ μŠ€ν”Œλ¦¬νŒ…μ„ νŽΈν•˜κ²Œ ν•˜λ„λ‘ λ„μ™€μ£ΌλŠ” μ„œλ“œνŒŒν‹° λΌμ΄λΈŒλŸ¬λ¦¬μ΄λ‹€.
  • 이 라이브러리의 이점은 μ„œλ²„ μ‚¬μ΄λ“œ λ Œλ”λ§μ„ μ§€μ›ν•œλ‹€. (React.lazy와 SuspenseλŠ” 아직 μ„œλ²„ μ‚¬μ΄λ“œ λ Œλ”λ§μ„ μ§€μ›ν•˜μ§€ μ•ŠλŠ”λ‹€.)
 const SplitMe = loadable(() => import("./SplitMe"), {
     fallback: <div>loading...</div>
 });
 
 SplitMe.preload(); // 미리 뢈러였기

✨ λ¦¬μ•‘νŠΈ λΌμš°ν„°μ™€ ν•¨κ»˜ μ‚¬μš©ν•˜κΈ°

import { BrowserRouter as Router, Route, Routes } from 'react-router-dom';
import loadable from "@loadable/component";

const Home = loadable(() => import('./routes/Home'));
const About = loadable(() => import('./routes/About'));

const App = () => (
  <Router>
    <Suspense fallback={<div>Loading...</div>}>
      <Routes>
        <Route path="/" element={<Home/>}/>
        <Route path="/about" element={<About/>}/>
      </Routes>
    </Suspense>
  </Router>
);
  • μ—¬λŸ¬ μ»΄ν¬λ„ŒνŠΈλ“€λ‘œ κ΅¬μ„±λœ 규λͺ¨κ°€ 큰 SPAλ₯Ό κ°œλ°œν•œλ‹€κ³  ν–ˆμ„ λ•Œ μ½”λ“œ μŠ€ν”Œλ¦¬νŒ…μ„ μ μš©ν•˜μ§€ μ•ŠμœΌλ©΄ μžλ°”μŠ€ν¬λ¦½νŠΈ main 파일이 μ»€μ§€κ²Œ λœλ‹€.
  • νŽ˜μ΄μ§€ λ‘œλ”© μ‹œ 아직 ν•„μš”ν•˜μ§€ μ•Šμ€ μ»΄ν¬λ„ŒνŠΈκΉŒμ§€ 뢈러였기 λ•Œλ¬Έμ— 졜초 νŽ˜μ΄μ§€ λ‘œλ”© μ‹œκ°„μ΄ 길어지고 μ‚¬μš©μž κ²½ν—˜μ΄ λ‚˜λΉ μ§„λ‹€.
  • κ·Έλž˜μ„œ μ½”λ“œ μŠ€ν”Œλ¦¬νŒ…μ„ 톡해 λ‹Ήμž₯ ν•„μš”ν•˜μ§€ μ•ŠλŠ” μ»΄ν¬λ„ŒνŠΈλ“€μ„ λΆ„λ¦¬μ‹œν‚€κ³  λ‚˜μ€‘μ— μ»΄ν¬λ„ŒνŠΈκ°€ λ Œλ”λ§λ˜λŠ” μ‹œμ μ— 뢈러올 수 μžˆμ–΄ 졜초 νŽ˜μ΄μ§€ λ‘œλ”© μ‹œκ°„μ„ κ°œμ„ ν•  수 μžˆλ‹€.

0개의 λŒ“κΈ€