Some chunks are larger than 500kB…(feat.lottie)

문다현·2024년 10월 26일
0
post-thumbnail

🔫 발단

아주 오래전부터 뜨던 이 warning이 계속 신경이 쓰였습니다.
경고문에 친절하게 해결책이 나와있습니다

  • 코드 스플리팅을 해봐!
  • 롤업옵션 manualChunk를 이용해서 분리를 해봐!
  • chunk limit 한도를 늘려봐!

이 해결책 중에 하나인 코드 스플리팅을 진행해서 괜찮을텐데 왜 아직도…?

🔫 문제가 될까?

사실 error가 아니라 warning이어서 지금까지 많이 보였지만 무시하고 해결을 하지 않았어요. 하지만 이번에 고치기로 마음 먹은 것은 현재 저희 팀이 성능 개선에 힘을 들이고 있는데 chunk의 크기가 성능과 사용자 경험과 관련이 있기 때문이에요.

대용량 청크 파일을 다운로드하는데 시간이 더 오래 걸려요.
특히 모바일 환경에서는 더!!
페이지 로드 동안 대기가 너무 길어지면 사용자가 이탈할 가능성이 훨씬 높아지겠죠??

결국 chunk파일의 용량을 적당한 크기로 운영하는 게 전반적인 성능을 챙기는 일이라고 판단했어요

🔫 혹시 스플리팅이 잘 안됐나? 싶어서 빌드하고 관찰

➡️ 매우 잘 되어있고. 그럼에도 불구하고 index가 500 kB가 넘어가요

용량이…even하지 않아요


🔫 visualizer로 관찰

로티 라이브러리가 상당히 커요

라우터별로 스플리팅을 진행해도 공통적으로 사용하는 것들이 index.js 에서 자리를 차지하기 때문에 저렇게 크기가 커질수도 있다고 합니다

⬇️ 밑 캡처에 나온 대로 롤업 옵션 활용해서 노드 모듈을 분리해봤어요

 manualChunks(id) {
      if (id.includes('node_modules')) {
        return 'vendor';  // node_modules에 있는 모듈들을 vendor로 분리
      }

더 큰일 발생….vendor chunk가 1000kB가 넘어갔습니다

🔫 라이브러리를 바꾸자

찾아보니까 현재쓰고 있는 lottie-react보다 lottie-web 이 더 가볍고 사람들이 더 많이 쓰더라고요

https://npmtrends.com/lottie-react-vs-lottie-web

좀더 찾아보니,

그도 그럴 수 밖에 없는데 두개가 별도의 라이브러리가 아니라 lottie-react가 lottie-web를 포함하는 래퍼 라이브러리였어요. 그 와중에 lottie-react는 react전용이기 때문에 리액트 컴포넌트로 작성이 되어있어서 편리하다는 점! 편리하지만 리액트기반의 코드들이 추가적으로 들어가있고, 그에 맞는 추가기능들이 붙어있기때문에 전체적으로 무거워진 것 같아요

🔫 내가 필요한 부분만 직접 구현하자!

그래서 결국에는 “lottie-react ⇒ lottie-web + 필요기능 직접 구현” 이라는 선택을 했는데요

import lottie from 'lottie-web';
import LoadingLottie from '../../assets/gifs/loading.json';

const Loading = () => {
  const spinnerRef = useRef<HTMLDivElement | null>(null); 

  useEffect(() => {
    const animation = lottie.loadAnimation({
      container: spinnerRef.current
      renderer: 'svg',
      loop: true,
      autoplay: true,
      animationData: LoadingLottie,
    });

    return () => animation.destroy(); //unmount시 종료
  }, []);

  return <SpinnerWrapper><Spinner ref={spinnerRef}/></SpinnerWrapper>; 
};

export default Loading;

생각보다 효과가 미미하네요(약 10kB 감소) 😅

🔫 lottie_light.min.js

분명히 라이브러리가 너무 크다고 불평하는 사람들이 많을것이다..하고 찾아보니
https://github.com/airbnb/lottie-web/issues/1184
역시나 불평이슈(?)가 있었고, 그 중 압도적인 따봉을 받은 코멘트 채택 후 코드 반영

⬇️ 요거 반영함!
했는데, ts에러가 뜨네요. lottie-web 깃허브에서 코드를 봤더니

lottie_light.min.d.ts 파일은 없어요 😭

경량을 목적으로 하다보니 타입도 안 쓴건가…?
또 공식 깃허브 뒤적뒤적✏️..

타입 추가된거 발견~!
https://github.com/airbnb/lottie-web/pull/1573

근데 자세히 보니 이 타입은 lottie_light.min.ts 가 아니라 lottie_light.ts였어요

차이가 클까 싶어서 또 사이즈 관찰해보니까 2.5kB 정도 차이밖에 안나서(169.87kB vs 171.31kB) 타입이 있는 lottie_light를 써도 되겠다 판단했어요.

참고로 사이즈 관찰은 source-map-explorer 써서 했어요

🔴 변경 전 <lottie-react> 315.68kB

🟢 변경 후 <lottie_light> - 171.31.kB

다시 빌드

이제 해당 경고문은 뜨지않아요~!!🎉🎉
다 500kB 언더이기때문!!! 하지만 500 가까운 수치가 조금 더 줄면 좋겠다고 생각했어요

🔫  아까 노드모듈 전부 넣고 폭발할뻔한 manualChunks 롤업 옵션을 다시 활용해보자

옵션 적용을 할때

  1. 로딩 순서 (초기 로딩에 필요하면 메인에 두는게 좋음)
  2. 기능적 연관성(비슷한 기능들끼리 묶는게 좋음)
  3. 캐싱이 자주 되기 때문에 변동이 잦지않는 것들을 분리하는 것이 좋음

을 고려를 하면 좋다하는데,

이러한 조건들을 따져봤을 때 리액트 모듈을 분리하면 효율적일 것 같다는 생각이 들었어요

  
    build: {
    rollupOptions: {
      output: {
        manualChunks: {
          vendor: ['react', 'react-dom', 'react-router-dom'],
        },
      },
    },
  },

🔫 결과

🔴 반영 전

🟢 반영 후

용량이 even하죠??

📚 참고한 자료들

https://bepyan.github.io/blog/2023/bundlers#rollup

https://simsimjae.medium.com/컴포넌트-레벨에서-웹팩으로-코드-스플리팅하기-cf34fe3a51c1

https://velog.io/@aborrencce/Vite-환경에서-Bundle-Analyzer로-최적화하기

https://velog.io/@seesaw/Vite-에서-build-chunks-사이즈를-줄여보자

https://medium.com/@younusraza909/code-splitting-optimization-react-cadf8c7daafc

profile
기록 남기기

0개의 댓글