본문 바로가기

Web Performance Optimization

[WPO] 컴포넌트 Preloading

.. 임시저장 되어있던 이 포스팅.. 모르고 삭제해버려서 다시 쓰는^^..

 

예전 글에서 Lazy Loading을 통해 Code Splitting 하는 과정을 기록해놨었다.

이 Lazy Loading에는 단점도 있는데..!

 

Lazy 로딩을 통해 최초 페이지에서는 속도가 빨라졌지만, 이때 로드해두지 않은 특정 컴포넌트를 선택하여 로드해야할 때 다소 느릴 수 있다는 점이다.

 

이 Lazy로딩의 단점 컴포넌트 Preloading으로 해결해보고자 한다!

 

 

 


 

🌱 컴포넌트 Preloading?

- 말 그대로 컴포넌트를 미리 로딩해 두는 것이다!

 

 

 

그럼 언제 컴포넌트를 미리 로드해야할까?

- 두가지 방법이 있다.

  1. 컴포넌트를 띄우는 버튼 위에 마우스를 올려 두었을 그 때!
  2. 최초 페이지 로드가 되고, 모든 컴포넌트의 마운트가 끝이 났을 때

 

하나씩 살펴보자!

 

 

 

1️⃣ ‘컴포넌트를 띄우는 버튼 위에 마우스를 올려놨을 때' 컴포넌트 Preloading을 하여 최적화를 해보자!

- onMouseEnter 이벤트 사용 : 마우스가 특정 컴포넌트 위에 올라왔을 때 실행됨

function App() {
    const [showModal, setShowModal] = useState(false)

		// 마우스가 버튼 위에 올라왔을 때, 필요한 component preloading!
    const handleMouseEnter = () => {
        const component = import('./components/ImageModal')
    }

    return (
        <div className="App">
            <Header />
            <InfoTable />
            <ButtonModal onClick={() => { setShowModal(true) }} onMouseEnter={handleMouseEnter}>올림픽 사진 보기</ButtonModal>
            <SurveyChart />
            <Footer />
            <Suspense fallback={null}> 
                {showModal ? <LazyImageModal closeModal={() => { setShowModal(false) }} /> : null}
            </Suspense>
        </div>
    )
}

Network 탭을 확인해보면, 마우스를 버튼 위에 올렸을 때 그 즉시 chunk 파일이 로드되는 것을 확인할 수 있다.

 

 

2️⃣ ‘최초 페이지 로드가 되고, 모든 컴포넌트의 마운트가 끝이 났을 때’ 컴포넌트 Preloading을 하여 최적화를 해보자!

- useEffect 사용

function App() {
    const [showModal, setShowModal] = useState(false)

    useEffect(()=> {
        const component = import('./components/ImageModal')
    }, [])

    return (
        <div className="App">
            <Header />
            <InfoTable />
            <ButtonModal onClick={() => { setShowModal(true) }}>올림픽 사진 보기</ButtonModal>
            <SurveyChart />
            <Footer />
            <Suspense fallback={null}> 
                {showModal ? <LazyImageModal closeModal={() => { setShowModal(false) }} /> : null}
            </Suspense>
        </div>
    )
}

→ Network 탭을 확인해보면, 중요한 컴포넌트들의 load가 끝난 뒤에, chunk 파일 두개가 바로 로드되는 것을 확인할 수 있다

 

 

 

📌 만약 여러 컴포넌트를 Preload 해야할 필요가 있을 경우, 간단하게 함수로 만들어서 편리하게 사용해보자!

function lazyWithPreload(importFunction) {
    const Component = React.lazy(importFunction)
    Component.preload = importFunction
    return Component
}

const LazyImageModal = lazyWithPreload(() => import('./components/ImageModal'))

function App() {
    const [showModal, setShowModal] = useState(false)

    // Component Preloading 1) 마우스가 버튼 위에 올라왔을 때, 필요한 component preloading!
    // const handleMouseEnter = () => {
    //     const component = import('./components/ImageModal')
    // }

    // Component Preloading 2) 최초 페이지 로드가 되고 모든 컴포넌트의 마운트가 끝이 났을 때, 필요한 component preloading!
    useEffect(()=> {
        LazyImageModal.preload()
    }, [])

    return (
        <div className="App">
            <Header />
            <InfoTable />
            <ButtonModal onClick={() => { setShowModal(true) }}>올림픽 사진 보기</ButtonModal>
            <SurveyChart />
            <Footer />
            <Suspense fallback={null}> 
                {showModal ? <LazyImageModal closeModal={() => { setShowModal(false) }} /> : null}
            </Suspense>
        </div>
    )
}

↑ Preload 함수(=import) 가 실행

 

 

 

 

 

 

 

 


Reference

Inflearn : 프론트엔드 개발자를 위한, 실전 웹 성능 최적화(feat. React)